Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-val
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-val
Commits
82d5a13c
Commit
82d5a13c
authored
Mar 16, 2017
by
Muhammad Ammar
Committed by
GitHub
Mar 16, 2017
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #69 from edx/ammar/tnl-6541-add-hls-profile
add hls profile
parents
d260fb65
084e2468
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
181 additions
and
48 deletions
+181
-48
edxval/migrations/0004_data__add_hls_profile.py
+30
-0
edxval/tests/constants.py
+29
-1
edxval/tests/test_api.py
+63
-9
edxval/tests/test_serializers.py
+7
-2
edxval/tests/test_views.py
+51
-35
setup.py
+1
-1
No files found.
edxval/migrations/0004_data__add_hls_profile.py
0 → 100644
View file @
82d5a13c
# -*- 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
),
]
edxval/tests/constants.py
View file @
82d5a13c
...
...
@@ -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
...
...
edxval/tests/test_api.py
View file @
82d5a13c
...
...
@@ -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
):
...
...
edxval/tests/test_serializers.py
View file @
82d5a13c
...
...
@@ -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
)
...
...
edxval/tests/test_views.py
View file @
82d5a13c
...
...
@@ -103,16 +103,17 @@ class VideoDetail(APIAuthTestCase):
constants
.
ENCODED_VIDEO_UPDATE_DICT_STAR
.
get
(
"url"
)
)
def
test_update_t
wo
_encoded_videos
(
self
):
def
test_update_t
hree
_encoded_videos
(
self
):
"""
Tests PUTting t
wo
encoded videos and then PUT back.
Tests PUTting t
hree
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_t
wo
_encoded_video_post
(
self
):
def
test_complete_set_t
hree
_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
...
...
setup.py
View file @
82d5a13c
...
...
@@ -39,7 +39,7 @@ def load_requirements(*requirements_paths):
setup
(
name
=
'edxval'
,
version
=
'0.0.1
2
'
,
version
=
'0.0.1
3
'
,
author
=
'edX'
,
url
=
'http://github.com/edx/edx-val'
,
description
=
'edx-val'
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment