Studio support for cohorted courseware
TNL-652
This commit is contained in:
49
cms/lib/xblock/authoring_mixin.py
Normal file
49
cms/lib/xblock/authoring_mixin.py
Normal file
@@ -0,0 +1,49 @@
|
||||
"""
|
||||
Mixin class that provides authoring capabilities for XBlocks.
|
||||
"""
|
||||
|
||||
import logging
|
||||
|
||||
from xblock.core import XBlock
|
||||
from xblock.fields import XBlockMixin
|
||||
from xblock.fragment import Fragment
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
VISIBILITY_VIEW = 'visibility_view'
|
||||
|
||||
|
||||
@XBlock.needs("i18n")
|
||||
class AuthoringMixin(XBlockMixin):
|
||||
"""
|
||||
Mixin class that provides authoring capabilities for XBlocks.
|
||||
"""
|
||||
_services_requested = {
|
||||
'i18n': 'need',
|
||||
}
|
||||
|
||||
def _get_studio_resource_url(self, relative_url):
|
||||
"""
|
||||
Returns the Studio URL to a static resource.
|
||||
"""
|
||||
# TODO: is there a cleaner way to do this?
|
||||
from cms.envs.common import STATIC_URL
|
||||
return STATIC_URL + relative_url
|
||||
|
||||
def visibility_view(self, _context=None):
|
||||
"""
|
||||
Render the view to manage an xblock's visibility settings in Studio.
|
||||
Args:
|
||||
_context: Not actively used for this view.
|
||||
Returns:
|
||||
(Fragment): An HTML fragment for editing the visibility of this XBlock.
|
||||
"""
|
||||
fragment = Fragment()
|
||||
from contentstore.utils import reverse_course_url
|
||||
fragment.add_content(self.system.render_template('visibility_editor.html', {
|
||||
'xblock': self,
|
||||
'manage_groups_url': reverse_course_url('group_configurations_list_handler', self.location.course_key),
|
||||
}))
|
||||
fragment.add_javascript_url(self._get_studio_resource_url('/js/xblock/authoring.js'))
|
||||
fragment.initialize_js('VisibilityEditorInit')
|
||||
return fragment
|
||||
121
cms/lib/xblock/test/test_authoring_mixin.py
Normal file
121
cms/lib/xblock/test/test_authoring_mixin.py
Normal file
@@ -0,0 +1,121 @@
|
||||
from openedx.core.djangoapps.course_groups.partition_scheme import CohortPartitionScheme
|
||||
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
|
||||
from xmodule.modulestore.tests.factories import CourseFactory, ItemFactory
|
||||
from xmodule.partitions.partitions import Group, UserPartition
|
||||
|
||||
|
||||
class AuthoringMixinTestCase(ModuleStoreTestCase):
|
||||
"""
|
||||
Tests the studio authoring XBlock mixin.
|
||||
"""
|
||||
def setUp(self):
|
||||
"""
|
||||
Create a simple course with a video component.
|
||||
"""
|
||||
super(AuthoringMixinTestCase, self).setUp()
|
||||
self.course = CourseFactory.create()
|
||||
chapter = ItemFactory.create(
|
||||
category='chapter',
|
||||
parent_location=self.course.location,
|
||||
display_name='Test Chapter'
|
||||
)
|
||||
sequential = ItemFactory.create(
|
||||
category='sequential',
|
||||
parent_location=chapter.location,
|
||||
display_name='Test Sequential'
|
||||
)
|
||||
self.vertical = ItemFactory.create(
|
||||
category='vertical',
|
||||
parent_location=sequential.location,
|
||||
display_name='Test Vertical'
|
||||
)
|
||||
self.video = ItemFactory.create(
|
||||
category='video',
|
||||
parent_location=self.vertical.location,
|
||||
display_name='Test Vertical'
|
||||
)
|
||||
self.pet_groups = [Group(1, 'Cat Lovers'), Group(2, 'Dog Lovers')]
|
||||
|
||||
def create_cohorted_content_groups(self, groups):
|
||||
"""
|
||||
Create a cohorted content partition with specified groups.
|
||||
"""
|
||||
self.content_partition = UserPartition(
|
||||
1,
|
||||
'Content Groups',
|
||||
'Contains Groups for Cohorted Courseware',
|
||||
groups,
|
||||
scheme_id='cohort'
|
||||
)
|
||||
self.course.user_partitions = [self.content_partition]
|
||||
self.store.update_item(self.course, self.user.id)
|
||||
|
||||
def set_staff_only(self, item):
|
||||
"""Make an item visible to staff only."""
|
||||
item.visible_to_staff_only = True
|
||||
self.store.update_item(item, self.user.id)
|
||||
|
||||
def set_group_access(self, item, group_ids):
|
||||
"""
|
||||
Set group_access for the specified item to the specified group
|
||||
ids within the content partition.
|
||||
"""
|
||||
item.group_access[self.content_partition.id] = group_ids
|
||||
self.store.update_item(item, self.user.id)
|
||||
|
||||
def verify_visibility_view_contains(self, item, substrings):
|
||||
"""
|
||||
Verify that an item's visibility view returns an html string
|
||||
containing all the expected substrings.
|
||||
"""
|
||||
html = item.visibility_view().body_html()
|
||||
for string in substrings:
|
||||
self.assertIn(string, html)
|
||||
|
||||
def test_html_no_partition(self):
|
||||
self.verify_visibility_view_contains(self.video, 'You have not set up any groups to manage visibility with.')
|
||||
|
||||
def test_html_empty_partition(self):
|
||||
self.create_cohorted_content_groups([])
|
||||
self.verify_visibility_view_contains(self.video, 'You have not set up any groups to manage visibility with.')
|
||||
|
||||
def test_html_populated_partition(self):
|
||||
self.create_cohorted_content_groups(self.pet_groups)
|
||||
self.verify_visibility_view_contains(self.video, ['Cat Lovers', 'Dog Lovers'])
|
||||
|
||||
def test_html_no_partition_staff_locked(self):
|
||||
self.set_staff_only(self.vertical)
|
||||
self.verify_visibility_view_contains(self.video, ['You have not set up any groups to manage visibility with.'])
|
||||
|
||||
def test_html_empty_partition_staff_locked(self):
|
||||
self.create_cohorted_content_groups([])
|
||||
self.set_staff_only(self.vertical)
|
||||
self.verify_visibility_view_contains(self.video, 'You have not set up any groups to manage visibility with.')
|
||||
|
||||
def test_html_populated_partition_staff_locked(self):
|
||||
self.create_cohorted_content_groups(self.pet_groups)
|
||||
self.set_staff_only(self.vertical)
|
||||
self.verify_visibility_view_contains(
|
||||
self.video, ['The Unit this component is contained in is hidden from students.', 'Cat Lovers', 'Dog Lovers']
|
||||
)
|
||||
|
||||
def test_html_false_content_group(self):
|
||||
self.create_cohorted_content_groups(self.pet_groups)
|
||||
self.set_group_access(self.video, ['false_group_id'])
|
||||
self.verify_visibility_view_contains(
|
||||
self.video, ['Cat Lovers', 'Dog Lovers', 'Content group no longer exists.']
|
||||
)
|
||||
|
||||
def test_html_false_content_group_staff_locked(self):
|
||||
self.create_cohorted_content_groups(self.pet_groups)
|
||||
self.set_staff_only(self.vertical)
|
||||
self.set_group_access(self.video, ['false_group_id'])
|
||||
self.verify_visibility_view_contains(
|
||||
self.video,
|
||||
[
|
||||
'Cat Lovers',
|
||||
'Dog Lovers',
|
||||
'The Unit this component is contained in is hidden from students.',
|
||||
'Content group no longer exists.'
|
||||
]
|
||||
)
|
||||
Reference in New Issue
Block a user