Merge pull request #6797 from edx/mobile/perf_improvements
Mobile performance improvements
This commit is contained in:
@@ -304,14 +304,7 @@ class VideoDescriptor(VideoFields, VideoTranscriptsMixin, VideoStudioViewHandler
|
||||
self._field_data.set_many(self, field_data)
|
||||
del self.data
|
||||
|
||||
editable_fields = super(VideoDescriptor, self).editable_metadata_fields
|
||||
|
||||
self.source_visible = False
|
||||
# Set download_video field to default value if its not explicitly set for backward compatibility.
|
||||
download_video = editable_fields['download_video']
|
||||
if not download_video['explicitly_set']:
|
||||
self.download_video = self.download_video
|
||||
|
||||
if self.source:
|
||||
# If `source` field value exist in the `html5_sources` field values,
|
||||
# then delete `source` field value and use value from `html5_sources` field.
|
||||
@@ -320,14 +313,17 @@ class VideoDescriptor(VideoFields, VideoTranscriptsMixin, VideoStudioViewHandler
|
||||
self.download_video = True
|
||||
else: # Otherwise, `source` field value will be used.
|
||||
self.source_visible = True
|
||||
if not download_video['explicitly_set']:
|
||||
if not self.fields['download_video'].is_set_on(self):
|
||||
self.download_video = True
|
||||
|
||||
# Set download_video field to default value if its not explicitly set for backward compatibility.
|
||||
if not self.fields['download_video'].is_set_on(self):
|
||||
self.download_video = self.download_video
|
||||
|
||||
# for backward compatibility.
|
||||
# If course was existed and was not re-imported by the moment of adding `download_track` field,
|
||||
# we should enable `download_track` if following is true:
|
||||
download_track = editable_fields['download_track']
|
||||
if not download_track['explicitly_set'] and self.track:
|
||||
if not self.fields['download_track'].is_set_on(self) and self.track:
|
||||
self.download_track = True
|
||||
|
||||
def editor_saved(self, user, old_metadata, old_content):
|
||||
|
||||
@@ -403,7 +403,7 @@ class XModuleMixin(XBlockMixin):
|
||||
else:
|
||||
return [self.display_name_with_default]
|
||||
|
||||
def get_children(self):
|
||||
def get_children(self, usage_key_filter=lambda location: True):
|
||||
"""Returns a list of XBlock instances for the children of
|
||||
this module"""
|
||||
|
||||
@@ -413,6 +413,9 @@ class XModuleMixin(XBlockMixin):
|
||||
if getattr(self, '_child_instances', None) is None:
|
||||
self._child_instances = [] # pylint: disable=attribute-defined-outside-init
|
||||
for child_loc in self.children:
|
||||
# Skip if it doesn't satisfy the filter function
|
||||
if not usage_key_filter(child_loc):
|
||||
continue
|
||||
try:
|
||||
child = self.runtime.get_block(child_loc)
|
||||
if child is None:
|
||||
|
||||
@@ -1,27 +1,16 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""Video xmodule tests in mongo."""
|
||||
import json
|
||||
import unittest
|
||||
from collections import OrderedDict
|
||||
from mock import patch, PropertyMock, MagicMock
|
||||
from mock import patch, MagicMock
|
||||
|
||||
from django.conf import settings
|
||||
|
||||
from xblock.fields import ScopeIds
|
||||
from xblock.field_data import DictFieldData
|
||||
|
||||
from xmodule.video_module import create_youtube_string, VideoDescriptor
|
||||
from xmodule.video_module import create_youtube_string
|
||||
from xmodule.x_module import STUDENT_VIEW
|
||||
from xmodule.tests import get_test_descriptor_system
|
||||
from xmodule.tests.test_video import VideoDescriptorTestBase
|
||||
|
||||
from edxval.api import (
|
||||
ValVideoNotFoundError,
|
||||
get_video_info,
|
||||
create_profile,
|
||||
create_video
|
||||
)
|
||||
import mock
|
||||
from edxval.api import create_profile, create_video
|
||||
|
||||
from . import BaseTestXmodule
|
||||
from .test_video_xml import SOURCE_XML
|
||||
@@ -417,7 +406,7 @@ class TestGetHtmlMethod(BaseTestXmodule):
|
||||
# it'll just fall back to the values in the VideoDescriptor.
|
||||
self.assertIn("example_source.mp4", self.item_descriptor.render(STUDENT_VIEW).content)
|
||||
|
||||
@mock.patch('edxval.api.get_video_info')
|
||||
@patch('edxval.api.get_video_info')
|
||||
def test_get_html_with_mocked_edx_video_id(self, mock_get_video_info):
|
||||
mock_get_video_info.return_value = {
|
||||
'url': '/edxval/video/example',
|
||||
@@ -798,81 +787,22 @@ class TestVideoDescriptorInitialization(BaseTestXmodule):
|
||||
self.assertFalse(self.item_descriptor.source_visible)
|
||||
|
||||
def test_download_video_is_explicitly_set(self):
|
||||
with patch(
|
||||
'xmodule.editing_module.TabsEditingDescriptor.editable_metadata_fields',
|
||||
new_callable=PropertyMock,
|
||||
return_value={
|
||||
'download_video': {
|
||||
'default_value': False,
|
||||
'explicitly_set': True,
|
||||
'display_name': 'Video Download Allowed',
|
||||
'help': 'Show a link beneath the video to allow students to download the video.',
|
||||
'type': 'Boolean',
|
||||
'value': False,
|
||||
'field_name': 'download_video',
|
||||
'options': [
|
||||
{'display_name': "True", "value": True},
|
||||
{'display_name': "False", "value": False}
|
||||
],
|
||||
},
|
||||
'html5_sources': {
|
||||
'default_value': [],
|
||||
'explicitly_set': False,
|
||||
'display_name': 'Video Sources',
|
||||
'help': 'A list of filenames to be used with HTML5 video.',
|
||||
'type': 'List',
|
||||
'value': [u'http://youtu.be/3_yD_cEKoCk.mp4'],
|
||||
'field_name': 'html5_sources',
|
||||
'options': [],
|
||||
},
|
||||
'source': {
|
||||
'default_value': '',
|
||||
'explicitly_set': False,
|
||||
'display_name': 'Download Video',
|
||||
'help': 'The external URL to download the video.',
|
||||
'type': 'Generic',
|
||||
'value': u'http://example.org/video.mp4',
|
||||
'field_name': 'source',
|
||||
'options': [],
|
||||
},
|
||||
'track': {
|
||||
'default_value': '',
|
||||
'explicitly_set': False,
|
||||
'display_name': 'Download Transcript',
|
||||
'help': 'The external URL to download the timed transcript track.',
|
||||
'type': 'Generic',
|
||||
'value': u'http://some_track.srt',
|
||||
'field_name': 'track',
|
||||
'options': [],
|
||||
},
|
||||
'download_track': {
|
||||
'default_value': False,
|
||||
'explicitly_set': False,
|
||||
'display_name': 'Transcript Download Allowed',
|
||||
'help': 'Show a link beneath the video to allow students to download the transcript. Note: You must add a link to the HTML5 Transcript field above.',
|
||||
'type': 'Generic',
|
||||
'value': False,
|
||||
'field_name': 'download_track',
|
||||
'options': [],
|
||||
},
|
||||
'transcripts': {},
|
||||
'handout': {},
|
||||
}
|
||||
):
|
||||
metadata = {
|
||||
'track': u'http://some_track.srt',
|
||||
'source': 'http://example.org/video.mp4',
|
||||
'html5_sources': ['http://youtu.be/3_yD_cEKoCk.mp4'],
|
||||
}
|
||||
metadata = {
|
||||
'track': u'http://some_track.srt',
|
||||
'source': 'http://example.org/video.mp4',
|
||||
'html5_sources': ['http://youtu.be/3_yD_cEKoCk.mp4'],
|
||||
'download_video': False,
|
||||
}
|
||||
|
||||
self.initialize_module(metadata=metadata)
|
||||
self.initialize_module(metadata=metadata)
|
||||
|
||||
fields = self.item_descriptor.editable_metadata_fields
|
||||
self.assertIn('source', fields)
|
||||
fields = self.item_descriptor.editable_metadata_fields
|
||||
self.assertIn('source', fields)
|
||||
self.assertIn('download_video', fields)
|
||||
|
||||
self.assertFalse(self.item_descriptor.download_video)
|
||||
self.assertTrue(self.item_descriptor.source_visible)
|
||||
self.assertTrue(self.item_descriptor.download_track)
|
||||
self.assertFalse(self.item_descriptor.download_video)
|
||||
self.assertTrue(self.item_descriptor.source_visible)
|
||||
self.assertTrue(self.item_descriptor.download_track)
|
||||
|
||||
def test_source_is_empty(self):
|
||||
metadata = {
|
||||
|
||||
@@ -90,23 +90,32 @@ class CourseStatusAPITestCase(MobileAPITestCase):
|
||||
"""
|
||||
REVERSE_INFO = {'name': 'user-course-status', 'params': ['username', 'course_id']}
|
||||
|
||||
def _setup_course_skeleton(self):
|
||||
def setUp(self):
|
||||
"""
|
||||
Creates a basic course structure for our course
|
||||
"""
|
||||
section = ItemFactory.create(
|
||||
parent_location=self.course.location,
|
||||
super(CourseStatusAPITestCase, self).setUp()
|
||||
|
||||
self.section = ItemFactory.create(
|
||||
parent=self.course,
|
||||
category='chapter',
|
||||
)
|
||||
sub_section = ItemFactory.create(
|
||||
parent_location=section.location,
|
||||
self.sub_section = ItemFactory.create(
|
||||
parent=self.section,
|
||||
category='sequential',
|
||||
)
|
||||
unit = ItemFactory.create(
|
||||
parent_location=sub_section.location,
|
||||
self.unit = ItemFactory.create(
|
||||
parent=self.sub_section,
|
||||
category='vertical',
|
||||
)
|
||||
other_unit = ItemFactory.create(
|
||||
parent_location=sub_section.location,
|
||||
self.other_sub_section = ItemFactory.create(
|
||||
parent=self.section,
|
||||
category='sequential',
|
||||
)
|
||||
self.other_unit = ItemFactory.create(
|
||||
parent=self.other_sub_section,
|
||||
category='vertical',
|
||||
)
|
||||
return section, sub_section, unit, other_unit
|
||||
|
||||
|
||||
class TestCourseStatusGET(CourseStatusAPITestCase, MobileAuthUserTestMixin, MobileEnrolledCourseAccessTestMixin):
|
||||
@@ -115,13 +124,15 @@ class TestCourseStatusGET(CourseStatusAPITestCase, MobileAuthUserTestMixin, Mobi
|
||||
"""
|
||||
def test_success(self):
|
||||
self.login_and_enroll()
|
||||
(section, sub_section, unit, __) = self._setup_course_skeleton()
|
||||
|
||||
response = self.api_response()
|
||||
self.assertEqual(response.data["last_visited_module_id"], unicode(unit.location))
|
||||
self.assertEqual(
|
||||
response.data["last_visited_module_path"],
|
||||
[unicode(module.location) for module in [unit, sub_section, section, self.course]]
|
||||
response.data["last_visited_module_id"], # pylint: disable=no-member
|
||||
unicode(self.sub_section.location)
|
||||
)
|
||||
self.assertEqual(
|
||||
response.data["last_visited_module_path"], # pylint: disable=no-member
|
||||
[unicode(module.location) for module in [self.sub_section, self.section, self.course]]
|
||||
)
|
||||
|
||||
|
||||
@@ -135,37 +146,45 @@ class TestCourseStatusPATCH(CourseStatusAPITestCase, MobileAuthUserTestMixin, Mo
|
||||
|
||||
def test_success(self):
|
||||
self.login_and_enroll()
|
||||
(__, __, __, other_unit) = self._setup_course_skeleton()
|
||||
|
||||
response = self.api_response(data={"last_visited_module_id": unicode(other_unit.location)})
|
||||
self.assertEqual(response.data["last_visited_module_id"], unicode(other_unit.location))
|
||||
response = self.api_response(data={"last_visited_module_id": unicode(self.other_unit.location)})
|
||||
self.assertEqual(
|
||||
response.data["last_visited_module_id"], # pylint: disable=no-member
|
||||
unicode(self.other_sub_section.location)
|
||||
)
|
||||
|
||||
def test_invalid_module(self):
|
||||
self.login_and_enroll()
|
||||
response = self.api_response(data={"last_visited_module_id": "abc"}, expected_response_code=400)
|
||||
self.assertEqual(response.data, errors.ERROR_INVALID_MODULE_ID)
|
||||
self.assertEqual(
|
||||
response.data, # pylint: disable=no-member
|
||||
errors.ERROR_INVALID_MODULE_ID
|
||||
)
|
||||
|
||||
def test_nonexistent_module(self):
|
||||
self.login_and_enroll()
|
||||
non_existent_key = self.course.id.make_usage_key('video', 'non-existent')
|
||||
response = self.api_response(data={"last_visited_module_id": non_existent_key}, expected_response_code=400)
|
||||
self.assertEqual(response.data, errors.ERROR_INVALID_MODULE_ID)
|
||||
self.assertEqual(
|
||||
response.data, # pylint: disable=no-member
|
||||
errors.ERROR_INVALID_MODULE_ID
|
||||
)
|
||||
|
||||
def test_no_timezone(self):
|
||||
self.login_and_enroll()
|
||||
(__, __, __, other_unit) = self._setup_course_skeleton()
|
||||
|
||||
past_date = datetime.datetime.now()
|
||||
response = self.api_response(
|
||||
data={
|
||||
"last_visited_module_id": unicode(other_unit.location),
|
||||
"last_visited_module_id": unicode(self.other_unit.location),
|
||||
"modification_date": past_date.isoformat() # pylint: disable=maybe-no-member
|
||||
},
|
||||
expected_response_code=400
|
||||
)
|
||||
self.assertEqual(response.data, errors.ERROR_INVALID_MODIFICATION_DATE)
|
||||
self.assertEqual(
|
||||
response.data, # pylint: disable=no-member
|
||||
errors.ERROR_INVALID_MODIFICATION_DATE
|
||||
)
|
||||
|
||||
def _date_sync(self, date, initial_unit, update_unit, expected_unit):
|
||||
def _date_sync(self, date, initial_unit, update_unit, expected_subsection):
|
||||
"""
|
||||
Helper for test cases that use a modification to decide whether
|
||||
to update the course status
|
||||
@@ -182,36 +201,41 @@ class TestCourseStatusPATCH(CourseStatusAPITestCase, MobileAuthUserTestMixin, Mo
|
||||
"modification_date": date.isoformat()
|
||||
}
|
||||
)
|
||||
self.assertEqual(response.data["last_visited_module_id"], unicode(expected_unit.location))
|
||||
self.assertEqual(
|
||||
response.data["last_visited_module_id"], # pylint: disable=no-member
|
||||
unicode(expected_subsection.location)
|
||||
)
|
||||
|
||||
def test_old_date(self):
|
||||
self.login_and_enroll()
|
||||
(__, __, unit, other_unit) = self._setup_course_skeleton()
|
||||
date = timezone.now() + datetime.timedelta(days=-100)
|
||||
self._date_sync(date, unit, other_unit, unit)
|
||||
self._date_sync(date, self.unit, self.other_unit, self.sub_section)
|
||||
|
||||
def test_new_date(self):
|
||||
self.login_and_enroll()
|
||||
(__, __, unit, other_unit) = self._setup_course_skeleton()
|
||||
|
||||
date = timezone.now() + datetime.timedelta(days=100)
|
||||
self._date_sync(date, unit, other_unit, other_unit)
|
||||
self._date_sync(date, self.unit, self.other_unit, self.other_sub_section)
|
||||
|
||||
def test_no_initial_date(self):
|
||||
self.login_and_enroll()
|
||||
(__, __, _, other_unit) = self._setup_course_skeleton()
|
||||
response = self.api_response(
|
||||
data={
|
||||
"last_visited_module_id": unicode(other_unit.location),
|
||||
"last_visited_module_id": unicode(self.other_unit.location),
|
||||
"modification_date": timezone.now().isoformat()
|
||||
}
|
||||
)
|
||||
self.assertEqual(response.data["last_visited_module_id"], unicode(other_unit.location))
|
||||
self.assertEqual(
|
||||
response.data["last_visited_module_id"], # pylint: disable=no-member
|
||||
unicode(self.other_sub_section.location)
|
||||
)
|
||||
|
||||
def test_invalid_date(self):
|
||||
self.login_and_enroll()
|
||||
response = self.api_response(data={"modification_date": "abc"}, expected_response_code=400)
|
||||
self.assertEqual(response.data, errors.ERROR_INVALID_MODIFICATION_DATE)
|
||||
self.assertEqual(
|
||||
response.data, # pylint: disable=no-member
|
||||
errors.ERROR_INVALID_MODIFICATION_DATE
|
||||
)
|
||||
|
||||
|
||||
class TestCourseEnrollmentSerializer(MobileAPITestCase):
|
||||
|
||||
@@ -107,15 +107,14 @@ class UserCourseStatus(views.APIView):
|
||||
course.id, request.user, course, depth=2)
|
||||
|
||||
course_module = get_module_for_descriptor(request.user, request, course, field_data_cache, course.id)
|
||||
current = course_module
|
||||
|
||||
path = []
|
||||
child = current
|
||||
while child:
|
||||
path.append(child)
|
||||
child = get_current_child(current)
|
||||
if child:
|
||||
current = child
|
||||
path = [course_module]
|
||||
chapter = get_current_child(course_module, min_depth=2)
|
||||
if chapter is not None:
|
||||
path.append(chapter)
|
||||
section = get_current_child(chapter, min_depth=1)
|
||||
if section is not None:
|
||||
path.append(section)
|
||||
|
||||
path.reverse()
|
||||
return path
|
||||
@@ -160,7 +159,7 @@ class UserCourseStatus(views.APIView):
|
||||
save_positions_recursively_up(request.user, request, field_data_cache, module)
|
||||
return self._get_course_info(request, course)
|
||||
|
||||
@mobile_course_access()
|
||||
@mobile_course_access(depth=2)
|
||||
def get(self, request, course, *args, **kwargs): # pylint: disable=unused-argument
|
||||
"""
|
||||
Get the ID of the module that the specified user last visited in the specified course.
|
||||
@@ -168,7 +167,7 @@ class UserCourseStatus(views.APIView):
|
||||
|
||||
return self._get_course_info(request, course)
|
||||
|
||||
@mobile_course_access()
|
||||
@mobile_course_access(depth=2)
|
||||
def patch(self, request, course, *args, **kwargs): # pylint: disable=unused-argument
|
||||
"""
|
||||
Update the ID of the module that the specified user last visited in the specified course.
|
||||
|
||||
@@ -5,11 +5,13 @@ Common utility methods and decorators for Mobile APIs.
|
||||
|
||||
import functools
|
||||
|
||||
from opaque_keys.edx.keys import CourseKey
|
||||
from courseware.courses import get_course_with_access
|
||||
from rest_framework import permissions
|
||||
from rest_framework.authentication import OAuth2Authentication, SessionAuthentication
|
||||
|
||||
from opaque_keys.edx.keys import CourseKey
|
||||
from xmodule.modulestore.django import modulestore
|
||||
from courseware.courses import get_course_with_access
|
||||
|
||||
|
||||
def mobile_course_access(depth=0, verify_enrolled=True):
|
||||
"""
|
||||
@@ -25,13 +27,14 @@ def mobile_course_access(depth=0, verify_enrolled=True):
|
||||
Raises 404 if access to course is disallowed.
|
||||
"""
|
||||
course_id = CourseKey.from_string(kwargs.pop('course_id'))
|
||||
course = get_course_with_access(
|
||||
request.user,
|
||||
'load_mobile' if verify_enrolled else 'load_mobile_no_enrollment_check',
|
||||
course_id,
|
||||
depth=depth
|
||||
)
|
||||
return func(self, request, course=course, *args, **kwargs)
|
||||
with modulestore().bulk_operations(course_id):
|
||||
course = get_course_with_access(
|
||||
request.user,
|
||||
'load_mobile' if verify_enrolled else 'load_mobile_no_enrollment_check',
|
||||
course_id,
|
||||
depth=depth
|
||||
)
|
||||
return func(self, request, course=course, *args, **kwargs)
|
||||
return _wrapper
|
||||
return _decorator
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ Serializer for video outline
|
||||
"""
|
||||
from rest_framework.reverse import reverse
|
||||
|
||||
from xmodule.modulestore.mongo.base import BLOCK_TYPES_WITH_CHILDREN
|
||||
from courseware.access import has_access
|
||||
|
||||
from edxval.api import (
|
||||
@@ -14,10 +15,10 @@ class BlockOutline(object):
|
||||
"""
|
||||
Serializes course videos, pulling data from VAL and the video modules.
|
||||
"""
|
||||
def __init__(self, course_id, start_block, categories_to_outliner, request):
|
||||
def __init__(self, course_id, start_block, block_types, request):
|
||||
"""Create a BlockOutline using `start_block` as a starting point."""
|
||||
self.start_block = start_block
|
||||
self.categories_to_outliner = categories_to_outliner
|
||||
self.block_types = block_types
|
||||
self.course_id = course_id
|
||||
self.request = request # needed for making full URLS
|
||||
self.local_cache = {}
|
||||
@@ -143,11 +144,11 @@ class BlockOutline(object):
|
||||
# from the table-of-contents.
|
||||
continue
|
||||
|
||||
if curr_block.category in self.categories_to_outliner:
|
||||
if curr_block.location.block_type in self.block_types:
|
||||
if not has_access(user, 'load', curr_block, course_key=self.course_id):
|
||||
continue
|
||||
|
||||
summary_fn = self.categories_to_outliner[curr_block.category]
|
||||
summary_fn = self.block_types[curr_block.category]
|
||||
block_path = list(path(curr_block))
|
||||
unit_url, section_url = find_urls(curr_block)
|
||||
|
||||
@@ -159,8 +160,17 @@ class BlockOutline(object):
|
||||
"summary": summary_fn(self.course_id, curr_block, self.request, self.local_cache)
|
||||
}
|
||||
|
||||
def parent_or_requested_block_type(usage_key):
|
||||
"""
|
||||
Returns whether the usage_key's block_type is one of self.block_types or a parent type.
|
||||
"""
|
||||
return (
|
||||
usage_key.block_type in self.block_types or
|
||||
usage_key.block_type in BLOCK_TYPES_WITH_CHILDREN
|
||||
)
|
||||
|
||||
if curr_block.has_children:
|
||||
for block in reversed(curr_block.get_children()):
|
||||
for block in reversed(curr_block.get_children(usage_key_filter=parent_or_requested_block_type)):
|
||||
stack.append(block)
|
||||
child_to_parent[block] = curr_block
|
||||
|
||||
|
||||
@@ -20,42 +20,42 @@ class TestVideoAPITestCase(MobileAPITestCase):
|
||||
def setUp(self):
|
||||
super(TestVideoAPITestCase, self).setUp()
|
||||
self.section = ItemFactory.create(
|
||||
parent_location=self.course.location,
|
||||
parent=self.course,
|
||||
category="chapter",
|
||||
display_name=u"test factory section omega \u03a9",
|
||||
)
|
||||
self.sub_section = ItemFactory.create(
|
||||
parent_location=self.section.location,
|
||||
parent=self.section,
|
||||
category="sequential",
|
||||
display_name=u"test subsection omega \u03a9",
|
||||
)
|
||||
|
||||
self.unit = ItemFactory.create(
|
||||
parent_location=self.sub_section.location,
|
||||
parent=self.sub_section,
|
||||
category="vertical",
|
||||
metadata={'graded': True, 'format': 'Homework'},
|
||||
display_name=u"test unit omega \u03a9",
|
||||
)
|
||||
self.other_unit = ItemFactory.create(
|
||||
parent_location=self.sub_section.location,
|
||||
parent=self.sub_section,
|
||||
category="vertical",
|
||||
metadata={'graded': True, 'format': 'Homework'},
|
||||
display_name=u"test unit omega 2 \u03a9",
|
||||
)
|
||||
self.nameless_unit = ItemFactory.create(
|
||||
parent_location=self.sub_section.location,
|
||||
parent=self.sub_section,
|
||||
category="vertical",
|
||||
metadata={'graded': True, 'format': 'Homework'},
|
||||
display_name=None,
|
||||
)
|
||||
self.split_unit = ItemFactory.create(
|
||||
parent_location=self.sub_section.location,
|
||||
parent=self.sub_section,
|
||||
category="vertical",
|
||||
display_name=u"split test vertical\u03a9",
|
||||
)
|
||||
|
||||
self.split_test = ItemFactory.create(
|
||||
parent_location=self.split_unit.location,
|
||||
parent=self.split_unit,
|
||||
category="split_test",
|
||||
display_name=u"split test unit"
|
||||
)
|
||||
@@ -120,7 +120,7 @@ class TestVideoAPITestCase(MobileAPITestCase):
|
||||
subid,
|
||||
self.course)
|
||||
return ItemFactory.create(
|
||||
parent_location=self.unit.location,
|
||||
parent=self.unit,
|
||||
category="video",
|
||||
edx_video_id=self.edx_video_id,
|
||||
display_name=u"test video omega \u03a9",
|
||||
@@ -156,27 +156,27 @@ class TestNonStandardCourseStructure(MobileAPITestCase):
|
||||
def setUp(self):
|
||||
super(TestNonStandardCourseStructure, self).setUp()
|
||||
self.chapter_under_course = ItemFactory.create(
|
||||
parent_location=self.course.location,
|
||||
parent=self.course,
|
||||
category="chapter",
|
||||
display_name=u"test factory chapter under course omega \u03a9",
|
||||
)
|
||||
self.section_under_course = ItemFactory.create(
|
||||
parent_location=self.course.location,
|
||||
parent=self.course,
|
||||
category="sequential",
|
||||
display_name=u"test factory section under course omega \u03a9",
|
||||
)
|
||||
self.section_under_chapter = ItemFactory.create(
|
||||
parent_location=self.chapter_under_course.location,
|
||||
parent=self.chapter_under_course,
|
||||
category="sequential",
|
||||
display_name=u"test factory section under chapter omega \u03a9",
|
||||
)
|
||||
self.vertical_under_course = ItemFactory.create(
|
||||
parent_location=self.course.location,
|
||||
parent=self.course,
|
||||
category="vertical",
|
||||
display_name=u"test factory vertical under course omega \u03a9",
|
||||
)
|
||||
self.vertical_under_section = ItemFactory.create(
|
||||
parent_location=self.section_under_chapter.location,
|
||||
parent=self.section_under_chapter,
|
||||
category="vertical",
|
||||
display_name=u"test factory vertical under section omega \u03a9",
|
||||
)
|
||||
@@ -187,7 +187,7 @@ class TestNonStandardCourseStructure(MobileAPITestCase):
|
||||
"""
|
||||
self.login_and_enroll()
|
||||
ItemFactory.create(
|
||||
parent_location=self.course.location,
|
||||
parent=self.course,
|
||||
category="video",
|
||||
display_name=u"test factory video omega \u03a9",
|
||||
)
|
||||
@@ -206,7 +206,7 @@ class TestNonStandardCourseStructure(MobileAPITestCase):
|
||||
"""
|
||||
self.login_and_enroll()
|
||||
ItemFactory.create(
|
||||
parent_location=self.vertical_under_course.location,
|
||||
parent=self.vertical_under_course,
|
||||
category="video",
|
||||
display_name=u"test factory video omega \u03a9",
|
||||
)
|
||||
@@ -234,7 +234,7 @@ class TestNonStandardCourseStructure(MobileAPITestCase):
|
||||
self.login_and_enroll()
|
||||
|
||||
ItemFactory.create(
|
||||
parent_location=self.chapter_under_course.location,
|
||||
parent=self.chapter_under_course,
|
||||
category="video",
|
||||
display_name=u"test factory video omega \u03a9",
|
||||
)
|
||||
@@ -262,7 +262,7 @@ class TestNonStandardCourseStructure(MobileAPITestCase):
|
||||
"""
|
||||
self.login_and_enroll()
|
||||
ItemFactory.create(
|
||||
parent_location=self.section_under_course.location,
|
||||
parent=self.section_under_course,
|
||||
category="video",
|
||||
display_name=u"test factory video omega \u03a9",
|
||||
)
|
||||
@@ -291,7 +291,7 @@ class TestNonStandardCourseStructure(MobileAPITestCase):
|
||||
self.login_and_enroll()
|
||||
|
||||
ItemFactory.create(
|
||||
parent_location=self.section_under_chapter.location,
|
||||
parent=self.section_under_chapter,
|
||||
category="video",
|
||||
display_name=u"meow factory video omega \u03a9",
|
||||
)
|
||||
@@ -323,7 +323,7 @@ class TestNonStandardCourseStructure(MobileAPITestCase):
|
||||
"""
|
||||
self.login_and_enroll()
|
||||
ItemFactory.create(
|
||||
parent_location=self.vertical_under_section.location,
|
||||
parent=self.vertical_under_section,
|
||||
category="video",
|
||||
display_name=u"test factory video omega \u03a9",
|
||||
)
|
||||
@@ -366,19 +366,19 @@ class TestVideoSummaryList(TestVideoAPITestCase, MobileAuthTestMixin, MobileEnro
|
||||
self.login_and_enroll()
|
||||
self._create_video_with_subs()
|
||||
ItemFactory.create(
|
||||
parent_location=self.other_unit.location,
|
||||
parent=self.other_unit,
|
||||
category="video",
|
||||
display_name=u"test video omega 2 \u03a9",
|
||||
html5_sources=[self.html5_video_url]
|
||||
)
|
||||
ItemFactory.create(
|
||||
parent_location=self.other_unit.location,
|
||||
parent=self.other_unit,
|
||||
category="video",
|
||||
display_name=u"test video omega 3 \u03a9",
|
||||
source=self.html5_video_url
|
||||
)
|
||||
ItemFactory.create(
|
||||
parent_location=self.unit.location,
|
||||
parent=self.unit,
|
||||
category="video",
|
||||
edx_video_id=self.edx_video_id,
|
||||
display_name=u"test draft video omega \u03a9",
|
||||
@@ -405,7 +405,7 @@ class TestVideoSummaryList(TestVideoAPITestCase, MobileAuthTestMixin, MobileEnro
|
||||
def test_with_nameless_unit(self):
|
||||
self.login_and_enroll()
|
||||
ItemFactory.create(
|
||||
parent_location=self.nameless_unit.location,
|
||||
parent=self.nameless_unit,
|
||||
category="video",
|
||||
edx_video_id=self.edx_video_id,
|
||||
display_name=u"test draft video omega 2 \u03a9"
|
||||
@@ -423,7 +423,7 @@ class TestVideoSummaryList(TestVideoAPITestCase, MobileAuthTestMixin, MobileEnro
|
||||
"""
|
||||
self.login_and_enroll()
|
||||
ItemFactory.create(
|
||||
parent_location=self.sub_section.location,
|
||||
parent=self.sub_section,
|
||||
category="video",
|
||||
edx_video_id=self.edx_video_id,
|
||||
display_name=u"video in the sub section"
|
||||
@@ -446,12 +446,12 @@ class TestVideoSummaryList(TestVideoAPITestCase, MobileAuthTestMixin, MobileEnro
|
||||
self.login_and_enroll()
|
||||
|
||||
ItemFactory.create(
|
||||
parent_location=self.split_test.location,
|
||||
parent=self.split_test,
|
||||
category="video",
|
||||
display_name=u"split test video a",
|
||||
)
|
||||
ItemFactory.create(
|
||||
parent_location=self.split_test.location,
|
||||
parent=self.split_test,
|
||||
category="video",
|
||||
display_name=u"split test video b",
|
||||
)
|
||||
@@ -465,26 +465,26 @@ class TestVideoSummaryList(TestVideoAPITestCase, MobileAuthTestMixin, MobileEnro
|
||||
def test_with_hidden_blocks(self):
|
||||
self.login_and_enroll()
|
||||
hidden_subsection = ItemFactory.create(
|
||||
parent_location=self.section.location,
|
||||
parent=self.section,
|
||||
category="sequential",
|
||||
hide_from_toc=True,
|
||||
)
|
||||
unit_within_hidden_subsection = ItemFactory.create(
|
||||
parent_location=hidden_subsection.location,
|
||||
parent=hidden_subsection,
|
||||
category="vertical",
|
||||
)
|
||||
hidden_unit = ItemFactory.create(
|
||||
parent_location=self.sub_section.location,
|
||||
parent=self.sub_section,
|
||||
category="vertical",
|
||||
hide_from_toc=True,
|
||||
)
|
||||
ItemFactory.create(
|
||||
parent_location=unit_within_hidden_subsection.location,
|
||||
parent=unit_within_hidden_subsection,
|
||||
category="video",
|
||||
edx_video_id=self.edx_video_id,
|
||||
)
|
||||
ItemFactory.create(
|
||||
parent_location=hidden_unit.location,
|
||||
parent=hidden_unit,
|
||||
category="video",
|
||||
edx_video_id=self.edx_video_id,
|
||||
)
|
||||
@@ -494,7 +494,7 @@ class TestVideoSummaryList(TestVideoAPITestCase, MobileAuthTestMixin, MobileEnro
|
||||
def test_language(self):
|
||||
self.login_and_enroll()
|
||||
video = ItemFactory.create(
|
||||
parent_location=self.nameless_unit.location,
|
||||
parent=self.nameless_unit,
|
||||
category="video",
|
||||
edx_video_id=self.edx_video_id,
|
||||
display_name=u"test draft video omega 2 \u03a9"
|
||||
@@ -523,7 +523,7 @@ class TestVideoSummaryList(TestVideoAPITestCase, MobileAuthTestMixin, MobileEnro
|
||||
def test_transcripts(self):
|
||||
self.login_and_enroll()
|
||||
video = ItemFactory.create(
|
||||
parent_location=self.nameless_unit.location,
|
||||
parent=self.nameless_unit,
|
||||
category="video",
|
||||
edx_video_id=self.edx_video_id,
|
||||
display_name=u"test draft video omega 2 \u03a9"
|
||||
|
||||
Reference in New Issue
Block a user