Commit 82d5a13c by Muhammad Ammar Committed by GitHub

Merge pull request #69 from edx/ammar/tnl-6541-add-hls-profile

add hls profile
parents d260fb65 084e2468
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import migrations, models
HLS_PROFILE = 'hls'
def create_hls_profile(apps, schema_editor):
""" Create hls profile """
Profile = apps.get_model("edxval", "Profile")
Profile.objects.get_or_create(profile_name=HLS_PROFILE)
def delete_hls_profile(apps, schema_editor):
""" Delete hls profile """
Profile = apps.get_model("edxval", "Profile")
Profile.objects.filter(profile_name=HLS_PROFILE).delete()
class Migration(migrations.Migration):
dependencies = [
('edxval', '0003_coursevideo_is_hidden'),
]
operations = [
migrations.RunPython(create_hls_profile, delete_hls_profile),
]
......@@ -10,6 +10,7 @@ Generic Profiles for manually creating profile objects
PROFILE_MOBILE = "mobile"
PROFILE_DESKTOP = "desktop"
PROFILE_YOUTUBE = "youtube"
PROFILE_HLS = 'hls'
"""
Encoded_videos for test_api, does not have profile.
"""
......@@ -43,6 +44,11 @@ ENCODED_VIDEO_DICT_DESKTOP3 = dict(
file_size=3333,
bitrate=4444,
)
ENCODED_VIDEO_DICT_HLS = dict(
url='https://www.tmnt.com/tmnt101.m3u8',
file_size=100,
bitrate=0
)
"""
Validators
"""
......@@ -150,6 +156,12 @@ ENCODED_VIDEO_DICT_FISH_DESKTOP = dict(
bitrate=4222,
profile="desktop",
)
ENCODED_VIDEO_DICT_FISH_HLS = dict(
url='https://www.tmnt.com/tmnt101.m3u8',
file_size=100,
bitrate=100,
profile='hls',
)
ENCODED_VIDEO_DICT_UPDATE_FISH_MOBILE = dict(
url="https://www.fishfellow.com",
file_size=1,
......@@ -162,6 +174,12 @@ ENCODED_VIDEO_DICT_UPDATE_FISH_DESKTOP = dict(
bitrate=2,
profile="desktop",
)
ENCODED_VIDEO_DICT_UPDATE_FISH_HLS = dict(
url="https://www.comics.com/flash/intro.m3u8",
file_size=200,
bitrate=200,
profile="hls",
)
ENCODED_VIDEO_DICT_FISH_INVALID_PROFILE = dict(
url="https://www.swordsplints.com",
file_size=1234,
......@@ -176,6 +194,15 @@ COMPLETE_SET_FISH = dict(
subtitles=[SUBTITLE_DICT_SRT, SUBTITLE_DICT_SJSON],
**VIDEO_DICT_FISH
)
COMPLETE_SET_FISH_WITH_HLS = dict(
encoded_videos=[
ENCODED_VIDEO_DICT_FISH_MOBILE,
ENCODED_VIDEO_DICT_FISH_DESKTOP,
ENCODED_VIDEO_DICT_FISH_HLS,
],
subtitles=[SUBTITLE_DICT_SRT, SUBTITLE_DICT_SJSON],
**VIDEO_DICT_FISH
)
COMPLETE_SET_TWO_MOBILE_FISH = dict(
encoded_videos=[
ENCODED_VIDEO_DICT_FISH_MOBILE,
......@@ -187,7 +214,8 @@ COMPLETE_SET_TWO_MOBILE_FISH = dict(
COMPLETE_SET_UPDATE_FISH = dict(
encoded_videos=[
ENCODED_VIDEO_DICT_UPDATE_FISH_MOBILE,
ENCODED_VIDEO_DICT_UPDATE_FISH_DESKTOP
ENCODED_VIDEO_DICT_UPDATE_FISH_DESKTOP,
ENCODED_VIDEO_DICT_UPDATE_FISH_HLS,
],
subtitles=[SUBTITLE_DICT_SRT],
**VIDEO_DICT_FISH
......
......@@ -98,7 +98,8 @@ class CreateVideoTest(TestCase):
video_data = dict(
encoded_videos=[
constants.ENCODED_VIDEO_DICT_FISH_MOBILE
constants.ENCODED_VIDEO_DICT_FISH_MOBILE,
constants.ENCODED_VIDEO_DICT_FISH_HLS
],
**constants.VIDEO_DICT_FISH
)
......@@ -198,12 +199,17 @@ class CreateProfileTest(TestCase):
"""
api.create_profile(constants.PROFILE_DESKTOP)
profiles = list(Profile.objects.all())
self.assertEqual(len(profiles), 6)
profile_names = [unicode(profile) for profile in profiles]
self.assertEqual(len(profiles), 7)
self.assertIn(
constants.PROFILE_DESKTOP,
[unicode(profile) for profile in profiles],
profile_names
)
self.assertIn(
constants.PROFILE_HLS,
profile_names
)
self.assertEqual(len(profiles), 6)
self.assertEqual(len(profiles), 7)
def test_invalid_create_profile(self):
"""
......@@ -240,6 +246,11 @@ class GetVideoInfoTest(TestCase):
profile=Profile.objects.get(profile_name="desktop"),
**constants.ENCODED_VIDEO_DICT_DESKTOP
)
EncodedVideo.objects.create(
video=video,
profile=Profile.objects.get(profile_name="hls"),
**constants.ENCODED_VIDEO_DICT_HLS
)
self.course_id = 'test-course'
CourseVideo.objects.create(video=video, course_id=self.course_id)
......@@ -308,6 +319,13 @@ class GetUrlsForProfileTest(TestCase):
profile=Profile.objects.get(profile_name="desktop"),
**constants.ENCODED_VIDEO_DICT_DESKTOP
)
EncodedVideo.objects.create(
video=Video.objects.get(
edx_video_id=constants.VIDEO_DICT_FISH.get("edx_video_id")
),
profile=Profile.objects.get(profile_name="hls"),
**constants.ENCODED_VIDEO_DICT_HLS
)
self.course_id = 'test-course'
CourseVideo.objects.create(video=video, course_id=self.course_id)
......@@ -315,12 +333,13 @@ class GetUrlsForProfileTest(TestCase):
"""
Tests when the profiles to the video are found
"""
profiles = ["mobile", "desktop"]
profiles = ["mobile", "desktop", 'hls']
edx_video_id = constants.VIDEO_DICT_FISH['edx_video_id']
urls = api.get_urls_for_profiles(edx_video_id, profiles)
self.assertEqual(len(urls), 2)
self.assertEqual(len(urls), 3)
self.assertEqual(urls["mobile"], u'http://www.meowmix.com')
self.assertEqual(urls["desktop"], u'http://www.meowmagic.com')
self.assertEqual(urls["hls"], u'https://www.tmnt.com/tmnt101.m3u8')
def test_get_urls_for_profiles_no_video(self):
"""
......@@ -357,11 +376,12 @@ class GetVideoForCourseProfiles(TestCase):
"""
Creates two courses for testing
Creates two videos with 2 encoded videos for the first course, and then
2 videos with 1 encoded video for the second course.
Creates two videos for first course where first video has 3 encodings and second
video has 2 encoding and then 2 videos with 1 encoded video for the second course.
"""
mobile_profile = Profile.objects.create(profile_name=constants.PROFILE_MOBILE)
desktop_profile = Profile.objects.create(profile_name=constants.PROFILE_DESKTOP)
hls_profile = Profile.objects.get(profile_name=constants.PROFILE_HLS)
self.course_id = 'test-course'
# 1st video
......@@ -376,6 +396,11 @@ class GetVideoForCourseProfiles(TestCase):
profile=desktop_profile,
**constants.ENCODED_VIDEO_DICT_DESKTOP
)
EncodedVideo.objects.create(
video=video,
profile=hls_profile,
**constants.ENCODED_VIDEO_DICT_HLS
)
CourseVideo.objects.create(video=video, course_id=self.course_id)
# 2nd video
video = Video.objects.create(**constants.VIDEO_DICT_STAR)
......@@ -553,6 +578,24 @@ class GetVideoForCourseProfiles(TestCase):
))
self.assertEqual(videos, expected_dict)
def test_get_video_for_course_profiles_hls(self):
"""
Tests get_video_info_for_course_and_profiles for hls profile
"""
videos = api.get_video_info_for_course_and_profiles(
self.course_id,
['hls']
)
self.assertEqual(
videos,
self._create_video_dict(
constants.VIDEO_DICT_FISH,
{
constants.PROFILE_HLS: constants.ENCODED_VIDEO_DICT_HLS
}
)
)
class GetVideosForCourseTest(TestCase, SortedVideoTestMixin):
"""
......@@ -814,6 +857,7 @@ class ExportTest(TestCase):
def setUp(self):
mobile_profile = Profile.objects.create(profile_name=constants.PROFILE_MOBILE)
desktop_profile = Profile.objects.create(profile_name=constants.PROFILE_DESKTOP)
hls_profile = Profile.objects.get(profile_name=constants.PROFILE_HLS)
Video.objects.create(**constants.VIDEO_DICT_STAR)
video = Video.objects.create(**constants.VIDEO_DICT_FISH)
EncodedVideo.objects.create(
......@@ -826,6 +870,11 @@ class ExportTest(TestCase):
profile=desktop_profile,
**constants.ENCODED_VIDEO_DICT_DESKTOP
)
EncodedVideo.objects.create(
video=video,
profile=hls_profile,
**constants.ENCODED_VIDEO_DICT_HLS
)
def assert_xml_equal(self, left, right):
"""
......@@ -861,6 +910,7 @@ class ExportTest(TestCase):
<video_asset client_video_id="Shallow Swordfish" duration="122.0">
<encoded_video url="http://www.meowmix.com" file_size="11" bitrate="22" profile="mobile"/>
<encoded_video url="http://www.meowmagic.com" file_size="33" bitrate="44" profile="desktop"/>
<encoded_video url="https://www.tmnt.com/tmnt101.m3u8" file_size="100" bitrate="0" profile="hls"/>
</video_asset>
""")
self.assert_xml_equal(
......@@ -935,7 +985,7 @@ class ImportTest(TestCase):
xml = self.make_import_xml(
video_dict=constants.VIDEO_DICT_STAR,
encoded_video_dicts=[constants.ENCODED_VIDEO_DICT_STAR]
encoded_video_dicts=[constants.ENCODED_VIDEO_DICT_STAR, constants.ENCODED_VIDEO_DICT_FISH_HLS]
)
api.import_from_xml(xml, constants.VIDEO_DICT_STAR["edx_video_id"], new_course_id)
......@@ -945,6 +995,10 @@ class ImportTest(TestCase):
video.encoded_videos.get(profile__profile_name=constants.PROFILE_MOBILE),
constants.ENCODED_VIDEO_DICT_STAR
)
self.assert_encoded_video_matches_dict(
video.encoded_videos.get(profile__profile_name=constants.PROFILE_HLS),
constants.ENCODED_VIDEO_DICT_FISH_HLS
)
video.courses.get(course_id=new_course_id)
def test_new_video_minimal(self):
......
......@@ -116,9 +116,14 @@ class SerializerTests(TestCase):
profile=Profile.objects.get(profile_name="mobile"),
**constants.ENCODED_VIDEO_DICT_MOBILE
)
EncodedVideo.objects.create(
video=video,
profile=Profile.objects.get(profile_name="hls"),
**constants.ENCODED_VIDEO_DICT_HLS
)
result = VideoSerializer(video).data # pylint: disable=E1101
# Check for 2 EncodedVideo entries
self.assertEqual(len(result.get("encoded_videos")), 2)
# Check for 3 EncodedVideo entries
self.assertEqual(len(result.get("encoded_videos")), 3)
# Check for original Video data
self.assertDictContainsSubset(constants.VIDEO_DICT_FISH, result)
......
......@@ -103,16 +103,17 @@ class VideoDetail(APIAuthTestCase):
constants.ENCODED_VIDEO_UPDATE_DICT_STAR.get("url")
)
def test_update_two_encoded_videos(self):
def test_update_three_encoded_videos(self):
"""
Tests PUTting two encoded videos and then PUT back.
Tests PUTting three encoded videos and then PUT back.
"""
url = reverse('video-list')
response = self.client.post(url, constants.COMPLETE_SET_FISH, format='json')
response = self.client.post(url, constants.COMPLETE_SET_FISH_WITH_HLS, format='json')
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
url = reverse(
'video-detail',
kwargs={"edx_video_id": constants.COMPLETE_SET_FISH.get("edx_video_id")}
kwargs={"edx_video_id": constants.COMPLETE_SET_FISH_WITH_HLS.get("edx_video_id")}
)
response = self.client.patch( # pylint: disable=E1101
path=url,
......@@ -122,41 +123,36 @@ class VideoDetail(APIAuthTestCase):
self.assertEqual(response.status_code, status.HTTP_200_OK)
videos = Video.objects.all()
self.assertEqual(len(videos), 1)
self.assertEqual(len(videos[0].encoded_videos.all()), 2)
first_url = videos[0].encoded_videos.all()[0].url
self.assertNotEqual(
constants.ENCODED_VIDEO_DICT_FISH_MOBILE,
constants.ENCODED_VIDEO_DICT_UPDATE_FISH_MOBILE.get("url"))
self.assertEqual(
first_url,
constants.ENCODED_VIDEO_DICT_UPDATE_FISH_MOBILE.get("url")
)
second_url = videos[0].encoded_videos.all()[1].url
self.assertNotEqual(
constants.ENCODED_VIDEO_DICT_FISH_DESKTOP,
constants.ENCODED_VIDEO_DICT_UPDATE_FISH_DESKTOP.get("url"))
self.assertEqual(
second_url,
constants.ENCODED_VIDEO_DICT_UPDATE_FISH_DESKTOP.get("url")
)
self.assertEqual(len(videos[0].encoded_videos.all()), 3)
for index, encoding in enumerate(videos[0].encoded_videos.all()):
before_update_encoding = constants.COMPLETE_SET_FISH_WITH_HLS['encoded_videos'][index]
after_update_encoding = constants.COMPLETE_SET_UPDATE_FISH['encoded_videos'][index]
self.assertNotEqual(
before_update_encoding.get('url'),
after_update_encoding.get('url')
)
self.assertEqual(
encoding.url,
after_update_encoding.get('url')
)
response = self.client.put(
path=url,
data=constants.COMPLETE_SET_FISH,
data=constants.COMPLETE_SET_FISH_WITH_HLS,
format='json'
)
self.assertEqual(response.status_code, status.HTTP_200_OK)
videos = Video.objects.all()
self.assertEqual(len(videos), 1)
first_url = videos[0].encoded_videos.all()[0].url
self.assertEqual(
first_url,
constants.ENCODED_VIDEO_DICT_FISH_MOBILE.get("url")
)
second_url = videos[0].encoded_videos.all()[1].url
self.assertEqual(
second_url,
constants.ENCODED_VIDEO_DICT_FISH_DESKTOP.get("url")
)
self.assertEqual(len(videos[0].encoded_videos.all()), 3)
for index, encoding in enumerate(videos[0].encoded_videos.all()):
self.assertEqual(
encoding.url,
constants.COMPLETE_SET_FISH_WITH_HLS['encoded_videos'][index].get('url')
)
def test_update_one_of_two_encoded_videos(self):
"""
......@@ -418,18 +414,18 @@ class VideoListTest(APIAuthTestCase):
Video.objects.all().delete()
# Tests for successful POST 201 requests.
def test_complete_set_two_encoded_video_post(self):
def test_complete_set_three_encoded_video_post(self):
"""
Tests POSTing Video and EncodedVideo pair
""" # pylint: disable=R0801
url = reverse('video-list')
response = self.client.post(
url, constants.COMPLETE_SET_FISH, format='json'
url, constants.COMPLETE_SET_FISH_WITH_HLS, format='json'
)
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
video = self.client.get("/edxval/videos/").data
self.assertEqual(len(video), 1)
self.assertEqual(len(video[0].get("encoded_videos")), 2)
self.assertEqual(len(video[0].get("encoded_videos")), 3)
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
def test_complete_set_with_extra_video_field(self):
......@@ -625,6 +621,26 @@ class VideoListTest(APIAuthTestCase):
self.assertEqual(len(response), 1)
self.assertEqual(response[0]['edx_video_id'], video['edx_video_id'])
def test_post_with_hls(self):
"""
Test that hls is a valid profile.
"""
url = reverse('video-list')
video_data = dict(
encoded_videos=[
constants.ENCODED_VIDEO_DICT_FISH_HLS
],
**constants.VIDEO_DICT_FISH
)
response = self.client.post(
url, video_data, format='json'
)
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
videos = self.client.get(url).data
self.assertEqual(len(videos), 1)
self.assertIn('https://www.tmnt.com/tmnt101.m3u8', videos[0]['encoded_videos'][0]['url'])
# Tests for POST queries to database
......
......@@ -39,7 +39,7 @@ def load_requirements(*requirements_paths):
setup(
name='edxval',
version='0.0.12',
version='0.0.13',
author='edX',
url='http://github.com/edx/edx-val',
description='edx-val',
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment