Commit 8778a639 by Nimisha Asthagiri

Merge pull request #32 from edx/mobile/video_upload-val

Support for studio-based Video Pipeline.
parents e39fcbc8 19e0e23f
edx-val edx-val
======= =======
Note:
The naming convetion for the `profile_name` in `Profile` objects will be the
medium of the profile (a-z), an underscore, and then the quality (a-z).
Examples:
desktop_high
mobile_medium
somethingelse_low
...@@ -22,7 +22,7 @@ class CourseVideoInline(admin.TabularInline): # pylint: disable=C0111 ...@@ -22,7 +22,7 @@ class CourseVideoInline(admin.TabularInline): # pylint: disable=C0111
class VideoAdmin(admin.ModelAdmin): # pylint: disable=C0111 class VideoAdmin(admin.ModelAdmin): # pylint: disable=C0111
list_display = ( list_display = (
'id', 'edx_video_id', 'client_video_id', 'duration' 'id', 'edx_video_id', 'client_video_id', 'duration', 'created', 'status'
) )
list_display_links = ('id', 'edx_video_id') list_display_links = ('id', 'edx_video_id')
search_fields = ('id', 'edx_video_id', 'client_video_id') search_fields = ('id', 'edx_video_id', 'client_video_id')
......
...@@ -51,6 +51,7 @@ class ValCannotCreateError(ValError): ...@@ -51,6 +51,7 @@ class ValCannotCreateError(ValError):
""" """
pass pass
def create_video(video_data): def create_video(video_data):
""" """
Called on to create Video objects in the database Called on to create Video objects in the database
...@@ -85,6 +86,7 @@ def create_video(video_data): ...@@ -85,6 +86,7 @@ def create_video(video_data):
else: else:
raise ValCannotCreateError(serializer.errors) raise ValCannotCreateError(serializer.errors)
def create_profile(profile_data): def create_profile(profile_data):
""" """
Used to create Profile objects in the database Used to create Profile objects in the database
...@@ -129,6 +131,7 @@ def get_video_info(edx_video_id, location=None): # pylint: disable=W0613 ...@@ -129,6 +131,7 @@ def get_video_info(edx_video_id, location=None): # pylint: disable=W0613
{ {
url: api url to the video url: api url to the video
edx_video_id: ID of the video edx_video_id: ID of the video
status: Status of the video as a string
duration: Length of video in seconds duration: Length of video in seconds
client_video_id: client ID of video client_video_id: client ID of video
encoded_video: a list of EncodedVideo dicts encoded_video: a list of EncodedVideo dicts
...@@ -181,10 +184,19 @@ def get_video_info(edx_video_id, location=None): # pylint: disable=W0613 ...@@ -181,10 +184,19 @@ def get_video_info(edx_video_id, location=None): # pylint: disable=W0613
raise ValInternalError(error_message) raise ValInternalError(error_message)
return result.data # pylint: disable=E1101 return result.data # pylint: disable=E1101
def get_urls_for_profiles(edx_video_id, profiles): def get_urls_for_profiles(edx_video_id, profiles):
"""Returns a dict mapping profiles to URLs. """
Returns a dict mapping profiles to URLs.
If the profiles or video is not found, urls will be blank. If the profiles or video is not found, urls will be blank.
Args:
edx_video_id (str): id of the video
profiles (list): list of profiles we want to search for
Returns:
profiles_to_urls (dict): A dict containing the profile to url pair
""" """
profiles_to_urls = {profile: None for profile in profiles} profiles_to_urls = {profile: None for profile in profiles}
try: try:
...@@ -198,11 +210,23 @@ def get_urls_for_profiles(edx_video_id, profiles): ...@@ -198,11 +210,23 @@ def get_urls_for_profiles(edx_video_id, profiles):
return profiles_to_urls return profiles_to_urls
def get_url_for_profile(edx_video_id, profile): def get_url_for_profile(edx_video_id, profile):
""" """
Uses get_urls_for_profile to obtain a single profile Uses get_urls_for_profile to obtain a single profile
Args:
edx_video_id (str): id of the video
profile (str): a string of the profile we are searching
Returns:
A dict containing the profile to url. The return type is the same as
get_urls_for_profiles for consistency.
""" """
return get_urls_for_profiles(edx_video_id, [profile])[profile] url = get_urls_for_profiles(edx_video_id, [profile])[profile]
return {profile: url}
def get_videos_for_course(course_id): def get_videos_for_course(course_id):
""" """
...@@ -211,8 +235,24 @@ def get_videos_for_course(course_id): ...@@ -211,8 +235,24 @@ def get_videos_for_course(course_id):
videos = Video.objects.filter(courses__course_id=unicode(course_id)) videos = Video.objects.filter(courses__course_id=unicode(course_id))
return (VideoSerializer(video).data for video in videos) return (VideoSerializer(video).data for video in videos)
def get_videos_for_ids(edx_video_ids):
"""
Returns an iterator of videos that match the given list of ids
Args:
edx_video_ids (list)
Returns:
A generator expression that contains the videos found
"""
videos = Video.objects.filter(edx_video_id__in=edx_video_ids)
return (VideoSerializer(video).data for video in videos)
def get_video_info_for_course_and_profile(course_id, profile_name): def get_video_info_for_course_and_profile(course_id, profile_name):
"""Returns a dict mapping profiles to URLs. """
Returns a dict mapping profiles to URLs.
If the profiles or video is not found, urls will be blank. If the profiles or video is not found, urls will be blank.
""" """
......
...@@ -85,7 +85,7 @@ class Migration(SchemaMigration): ...@@ -85,7 +85,7 @@ class Migration(SchemaMigration):
models = { models = {
'edxval.coursevideos': { 'edxval.coursevideo': {
'Meta': {'unique_together': "(('course_id', 'video'),)", 'object_name': 'CourseVideo'}, 'Meta': {'unique_together': "(('course_id', 'video'),)", 'object_name': 'CourseVideo'},
'course_id': ('django.db.models.fields.CharField', [], {'max_length': '255'}), 'course_id': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
......
...@@ -24,7 +24,7 @@ class Migration(DataMigration): ...@@ -24,7 +24,7 @@ class Migration(DataMigration):
).delete() ).delete()
models = { models = {
'edxval.coursevideos': { 'edxval.coursevideo': {
'Meta': {'unique_together': "(('course_id', 'video'),)", 'object_name': 'CourseVideo'}, 'Meta': {'unique_together': "(('course_id', 'video'),)", 'object_name': 'CourseVideo'},
'course_id': ('django.db.models.fields.CharField', [], {'max_length': '255'}), 'course_id': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
......
# -*- coding: utf-8 -*-
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models
class Migration(SchemaMigration):
def forwards(self, orm):
# Adding field 'Video.created'
db.add_column('edxval_video', 'created',
self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, default=datetime.datetime(2014, 11, 17, 0, 0), blank=True),
keep_default=False)
# Adding field 'Video.status'
db.add_column('edxval_video', 'status',
self.gf('django.db.models.fields.CharField')(default='File Complete', max_length=255, db_index=True),
keep_default=False)
# Changing field 'Video.edx_video_id'
db.alter_column('edxval_video', 'edx_video_id', self.gf('django.db.models.fields.CharField')(unique=True, max_length=100))
# Changing field 'EncodedVideo.url'
db.alter_column('edxval_encodedvideo', 'url', self.gf('django.db.models.fields.CharField')(max_length=200))
def backwards(self, orm):
# Deleting field 'Video.created'
db.delete_column('edxval_video', 'created')
# Deleting field 'Video.status'
db.delete_column('edxval_video', 'status')
# Changing field 'Video.edx_video_id'
db.alter_column('edxval_video', 'edx_video_id', self.gf('django.db.models.fields.CharField')(max_length=50, unique=True))
# Changing field 'EncodedVideo.url'
db.alter_column('edxval_encodedvideo', 'url', self.gf('django.db.models.fields.URLField')(max_length=200))
models = {
'edxval.coursevideo': {
'Meta': {'unique_together': "(('course_id', 'video'),)", 'object_name': 'CourseVideo'},
'course_id': ('django.db.models.fields.CharField', [], {'max_length': '255'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'video': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'courses'", 'to': "orm['edxval.Video']"})
},
'edxval.encodedvideo': {
'Meta': {'object_name': 'EncodedVideo'},
'bitrate': ('django.db.models.fields.PositiveIntegerField', [], {}),
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'file_size': ('django.db.models.fields.PositiveIntegerField', [], {}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'profile': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'+'", 'to': "orm['edxval.Profile']"}),
'url': ('django.db.models.fields.CharField', [], {'max_length': '200'}),
'video': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'encoded_videos'", 'to': "orm['edxval.Video']"})
},
'edxval.profile': {
'Meta': {'object_name': 'Profile'},
'extension': ('django.db.models.fields.CharField', [], {'max_length': '10'}),
'height': ('django.db.models.fields.PositiveIntegerField', [], {}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'profile_name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '50'}),
'width': ('django.db.models.fields.PositiveIntegerField', [], {})
},
'edxval.subtitle': {
'Meta': {'object_name': 'Subtitle'},
'content': ('django.db.models.fields.TextField', [], {'default': "''"}),
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'fmt': ('django.db.models.fields.CharField', [], {'max_length': '20', 'db_index': 'True'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'language': ('django.db.models.fields.CharField', [], {'max_length': '8', 'db_index': 'True'}),
'modified': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'video': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'subtitles'", 'to': "orm['edxval.Video']"})
},
'edxval.video': {
'Meta': {'object_name': 'Video'},
'client_video_id': ('django.db.models.fields.CharField', [], {'db_index': 'True', 'max_length': '255', 'blank': 'True'}),
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'duration': ('django.db.models.fields.FloatField', [], {}),
'edx_video_id': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}),
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'status': ('django.db.models.fields.CharField', [], {'max_length': '255', 'db_index': 'True'})
}
}
complete_apps = ['edxval']
\ No newline at end of file
""" """
Django models for videos for Video Abstraction Layer (VAL) Django models for videos for Video Abstraction Layer (VAL)
When calling a serializers' .errors function for objects, there is an When calling a serializers' .errors field, there is a priority in which the
order in which the errors are returned. This may cause a partial return of errors errors are returned. This may cause a partial return of errors, starting with
the highest priority.
Example: Example:
class Profile(models.Model) class Profile(models.Model)
...@@ -67,9 +68,14 @@ class Video(models.Model): ...@@ -67,9 +68,14 @@ class Video(models.Model):
A video can have multiple formats. This model are the fields that represent A video can have multiple formats. This model are the fields that represent
the collection of those videos that do not change across formats. the collection of those videos that do not change across formats.
Attributes:
status: Used to keep track of the processing video as it goes through
the video pipeline, e.g., "Uploading", "File Complete"...
""" """
created = models.DateTimeField(auto_now_add=True)
edx_video_id = models.CharField( edx_video_id = models.CharField(
max_length=50, max_length=100,
unique=True, unique=True,
validators=[ validators=[
RegexValidator( RegexValidator(
...@@ -81,6 +87,7 @@ class Video(models.Model): ...@@ -81,6 +87,7 @@ class Video(models.Model):
) )
client_video_id = models.CharField(max_length=255, db_index=True, blank=True) client_video_id = models.CharField(max_length=255, db_index=True, blank=True)
duration = models.FloatField(validators=[MinValueValidator(0)]) duration = models.FloatField(validators=[MinValueValidator(0)])
status = models.CharField(max_length=255, db_index=True)
def get_absolute_url(self): def get_absolute_url(self):
""" """
...@@ -107,8 +114,8 @@ class CourseVideo(models.Model): ...@@ -107,8 +114,8 @@ class CourseVideo(models.Model):
""" """
Model for the course_id associated with the video content. Model for the course_id associated with the video content.
Every course-semester has a unique course_id. A video can be paired with multiple Every course-semester has a unique course_id. A video can be paired with
course_id's but each pair is unique together. multiple course_id's but each pair is unique together.
""" """
course_id = models.CharField(max_length=255) course_id = models.CharField(max_length=255)
video = models.ForeignKey(Video, related_name='courses') video = models.ForeignKey(Video, related_name='courses')
...@@ -146,6 +153,10 @@ SUBTITLE_FORMATS = ( ...@@ -146,6 +153,10 @@ SUBTITLE_FORMATS = (
class Subtitle(models.Model): class Subtitle(models.Model):
""" """
Subtitle for video Subtitle for video
Attributes:
video: the video that the subtitles are for
fmt: the format of the subttitles file
""" """
created = models.DateTimeField(auto_now_add=True) created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True) modified = models.DateTimeField(auto_now=True)
......
...@@ -30,4 +30,4 @@ class APIAuthTestCase(APITestCase): ...@@ -30,4 +30,4 @@ class APIAuthTestCase(APITestCase):
username = password = 'unauthorized' username = password = 'unauthorized'
else: else:
username, password = self.username, self.password username, password = self.username, self.password
print self.client.login(username=username, password=password) self.client.login(username=username, password=password)
...@@ -45,6 +45,7 @@ VIDEO_DICT_NEGATIVE_DURATION = dict( ...@@ -45,6 +45,7 @@ VIDEO_DICT_NEGATIVE_DURATION = dict(
client_video_id="Thunder Cats S01E01", client_video_id="Thunder Cats S01E01",
duration=-111, duration=-111,
edx_video_id="thisis12char-thisis7", edx_video_id="thisis12char-thisis7",
status="test",
encoded_videos=[], encoded_videos=[],
subtitles=[] subtitles=[]
) )
...@@ -52,11 +53,13 @@ VIDEO_DICT_BEE_INVALID = dict( ...@@ -52,11 +53,13 @@ VIDEO_DICT_BEE_INVALID = dict(
client_video_id="Barking Bee", client_video_id="Barking Bee",
duration=111.00, duration=111.00,
edx_video_id="wa/sps", edx_video_id="wa/sps",
status="test",
) )
VIDEO_DICT_INVALID_ID = dict( VIDEO_DICT_INVALID_ID = dict(
client_video_id="SuperSloth", client_video_id="SuperSloth",
duration=42, duration=42,
edx_video_id="sloppy/sloth!!", edx_video_id="sloppy/sloth!!",
status="test",
encoded_videos=[], encoded_videos=[],
subtitles=[] subtitles=[]
) )
...@@ -77,6 +80,7 @@ VIDEO_DICT_NON_LATIN_TITLE = dict( ...@@ -77,6 +80,7 @@ VIDEO_DICT_NON_LATIN_TITLE = dict(
client_video_id=u"배고픈 햄스터", client_video_id=u"배고픈 햄스터",
duration=42, duration=42,
edx_video_id="ID", edx_video_id="ID",
status="test",
encoded_videos=[], encoded_videos=[],
subtitles=[] subtitles=[]
) )
...@@ -84,6 +88,7 @@ VIDEO_DICT_NON_LATIN_ID = dict( ...@@ -84,6 +88,7 @@ VIDEO_DICT_NON_LATIN_ID = dict(
client_video_id="Hungry Hamster", client_video_id="Hungry Hamster",
duration=42, duration=42,
edx_video_id="밥줘", edx_video_id="밥줘",
status="test",
encoded_videos=[], encoded_videos=[],
subtitles=[] subtitles=[]
) )
...@@ -140,12 +145,14 @@ Fish ...@@ -140,12 +145,14 @@ Fish
VIDEO_DICT_FISH = dict( VIDEO_DICT_FISH = dict(
client_video_id="Shallow Swordfish", client_video_id="Shallow Swordfish",
duration=122.00, duration=122.00,
edx_video_id="super-soaker" edx_video_id="super-soaker",
status="test",
) )
VIDEO_DICT_DIFFERENT_ID_FISH = dict( VIDEO_DICT_DIFFERENT_ID_FISH = dict(
client_video_id="Shallow Swordfish", client_video_id="Shallow Swordfish",
duration=122.00, duration=122.00,
edx_video_id="medium-soaker" edx_video_id="medium-soaker",
status="test",
) )
ENCODED_VIDEO_DICT_FISH_MOBILE = dict( ENCODED_VIDEO_DICT_FISH_MOBILE = dict(
url="https://www.swordsingers.com", url="https://www.swordsingers.com",
...@@ -242,6 +249,7 @@ COMPLETE_SET_INVALID_VIDEO_FISH = dict( ...@@ -242,6 +249,7 @@ COMPLETE_SET_INVALID_VIDEO_FISH = dict(
client_video_id="Shallow Swordfish", client_video_id="Shallow Swordfish",
duration=122.00, duration=122.00,
edx_video_id="super/soaker", edx_video_id="super/soaker",
status="test",
encoded_videos=[ encoded_videos=[
ENCODED_VIDEO_DICT_FISH_MOBILE, ENCODED_VIDEO_DICT_FISH_MOBILE,
ENCODED_VIDEO_DICT_FISH_DESKTOP ENCODED_VIDEO_DICT_FISH_DESKTOP
...@@ -259,7 +267,8 @@ Star ...@@ -259,7 +267,8 @@ Star
VIDEO_DICT_STAR = dict( VIDEO_DICT_STAR = dict(
client_video_id="TWINKLE TWINKLE", client_video_id="TWINKLE TWINKLE",
duration=122.00, duration=122.00,
edx_video_id="little-star" edx_video_id="little-star",
status="test",
) )
ENCODED_VIDEO_DICT_STAR = dict( ENCODED_VIDEO_DICT_STAR = dict(
url="https://www.howIwonder.com", url="https://www.howIwonder.com",
...@@ -317,6 +326,7 @@ VIDEO_DICT_ZEBRA = dict( ...@@ -317,6 +326,7 @@ VIDEO_DICT_ZEBRA = dict(
client_video_id="Zesty Zebra", client_video_id="Zesty Zebra",
duration=111.00, duration=111.00,
edx_video_id="zestttt", edx_video_id="zestttt",
status="test",
encoded_videos=[], encoded_videos=[],
subtitles=[] subtitles=[]
) )
...@@ -324,6 +334,7 @@ VIDEO_DICT_ANIMAL = dict( ...@@ -324,6 +334,7 @@ VIDEO_DICT_ANIMAL = dict(
client_video_id="Average Animal", client_video_id="Average Animal",
duration=111.00, duration=111.00,
edx_video_id="mediocrity", edx_video_id="mediocrity",
status="test",
encoded_videos=[], encoded_videos=[],
subtitles=[] subtitles=[]
) )
...@@ -331,6 +342,7 @@ VIDEO_DICT_UPDATE_ANIMAL = dict( ...@@ -331,6 +342,7 @@ VIDEO_DICT_UPDATE_ANIMAL = dict(
client_video_id="Above Average Animal", client_video_id="Above Average Animal",
duration=999.00, duration=999.00,
edx_video_id="mediocrity", edx_video_id="mediocrity",
status="test",
encoded_videos=[], encoded_videos=[],
subtitles=[] subtitles=[]
) )
...@@ -201,6 +201,141 @@ class GetVideoInfoTest(TestCase): ...@@ -201,6 +201,141 @@ class GetVideoInfoTest(TestCase):
) )
class GetUrlsForProfileTest(TestCase):
"""
Tests the get_urls_for_profile(s) function in api.py
"""
def setUp(self):
"""
Creates EncodedVideo objects in database
"""
Profile.objects.create(**constants.PROFILE_DICT_MOBILE)
Profile.objects.create(**constants.PROFILE_DICT_DESKTOP)
video = Video.objects.create(**constants.VIDEO_DICT_FISH)
EncodedVideo.objects.create(
video=Video.objects.get(
edx_video_id=constants.VIDEO_DICT_FISH.get("edx_video_id")
),
profile=Profile.objects.get(profile_name="mobile"),
**constants.ENCODED_VIDEO_DICT_MOBILE
)
EncodedVideo.objects.create(
video=Video.objects.get(
edx_video_id=constants.VIDEO_DICT_FISH.get("edx_video_id")
),
profile=Profile.objects.get(profile_name="desktop"),
**constants.ENCODED_VIDEO_DICT_DESKTOP
)
self.course_id = 'test-course'
CourseVideo.objects.create(video=video, course_id=self.course_id)
def test_get_urls_for_profiles(self):
"""
Tests when the profiles to the video are found
"""
profiles = ["mobile", "desktop"]
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(urls["mobile"], u'http://www.meowmix.com')
self.assertEqual(urls["desktop"], u'http://www.meowmagic.com')
def test_get_urls_for_profiles_no_video(self):
"""
Tests when there is no video found.
"""
urls = api.get_urls_for_profiles("not found", ["mobile"])
self.assertEqual(urls["mobile"], None)
def test_get_urls_for_profiles_no_profiles(self):
"""
Tests when the video is found, but not hte profiles.
"""
profiles = ["not", "found"]
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(urls["not"], None)
self.assertEqual(urls["found"], None)
def test_get_url_for_profile(self):
"""
Tests get_url_for_profile
"""
profile = "mobile"
edx_video_id = constants.VIDEO_DICT_FISH['edx_video_id']
urls = api.get_url_for_profile(edx_video_id, profile)
self.assertEqual(len(urls), 1)
self.assertEqual(urls["mobile"], u'http://www.meowmix.com')
class GetVideosForIds(TestCase):
"""
Tests the get_videos_for_ids function in api.py
"""
def setUp(self):
"""
Creates EncodedVideo objects in database
"""
Profile.objects.create(**constants.PROFILE_DICT_MOBILE)
Profile.objects.create(**constants.PROFILE_DICT_DESKTOP)
video = Video.objects.create(**constants.VIDEO_DICT_FISH)
EncodedVideo.objects.create(
video=Video.objects.get(
edx_video_id=constants.VIDEO_DICT_FISH.get("edx_video_id")
),
profile=Profile.objects.get(profile_name="mobile"),
**constants.ENCODED_VIDEO_DICT_MOBILE
)
EncodedVideo.objects.create(
video=Video.objects.get(
edx_video_id=constants.VIDEO_DICT_FISH.get("edx_video_id")
),
profile=Profile.objects.get(profile_name="desktop"),
**constants.ENCODED_VIDEO_DICT_DESKTOP
)
self.course_id = 'test-course'
CourseVideo.objects.create(video=video, course_id=self.course_id)
def test_get_videos_for_id(self):
"""
Tests retrieving videos for id
"""
edx_video_id = constants.VIDEO_DICT_FISH['edx_video_id']
videos = list(api.get_videos_for_ids([edx_video_id]))
self.assertEqual(len(videos), 1)
self.assertEqual(videos[0]['edx_video_id'], edx_video_id)
videos = list(api.get_videos_for_ids(['unknown']))
self.assertEqual(len(videos), 0)
def test_get_videos_for_ids(self):
"""
Tests retrieving videos for ids
"""
Video.objects.create(**constants.VIDEO_DICT_DIFFERENT_ID_FISH)
EncodedVideo.objects.create(
video=Video.objects.get(
edx_video_id=constants.VIDEO_DICT_DIFFERENT_ID_FISH.get("edx_video_id")
),
profile=Profile.objects.get(profile_name="mobile"),
**constants.ENCODED_VIDEO_DICT_MOBILE
)
edx_video_id = constants.VIDEO_DICT_FISH['edx_video_id']
edx_video_id_2 = constants.VIDEO_DICT_DIFFERENT_ID_FISH['edx_video_id']
videos = list(api.get_videos_for_ids([edx_video_id, edx_video_id_2]))
self.assertEqual(len(videos), 2)
def test_get_videos_for_ids_duplicates(self):
"""
Tests retrieving videos for ids when there are duplicate ids
"""
edx_video_id = constants.VIDEO_DICT_FISH['edx_video_id']
videos = list(api.get_videos_for_ids([edx_video_id, edx_video_id]))
self.assertEqual(len(videos), 1)
class GetVideoInfoTestWithHttpCalls(APIAuthTestCase): class GetVideoInfoTestWithHttpCalls(APIAuthTestCase):
""" """
Tests for the get_info_video, using the HTTP requests to populate database Tests for the get_info_video, using the HTTP requests to populate database
......
"""
Tests for Video Abstraction Layer models
"""
...@@ -72,7 +72,8 @@ class SerializerTests(TestCase): ...@@ -72,7 +72,8 @@ class SerializerTests(TestCase):
message = error.get("edx_video_id")[0] message = error.get("edx_video_id")[0]
self.assertEqual( self.assertEqual(
message, message,
u"edx_video_id has invalid characters") u"edx_video_id has invalid characters"
)
def test_encoded_video_set_output(self): def test_encoded_video_set_output(self):
""" """
......
...@@ -513,6 +513,7 @@ class VideoListTest(APIAuthTestCase): ...@@ -513,6 +513,7 @@ class VideoListTest(APIAuthTestCase):
""" """
video = { video = {
'edx_video_id': 'testing-youtube', 'edx_video_id': 'testing-youtube',
'status': 'test',
'encoded_videos': [ 'encoded_videos': [
{ {
'profile': 'youtube', 'profile': 'youtube',
......
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