Commit 58483c06 by Andy Armstrong

Fix split_test xblock so that it can render in Studio

This change addresses STUD-1403 where split_test modules could not render in Studio.
It changes Studio to pass a new parameter 'runtime-type' of 'studio' when rendering
 an xblock. In split_test, this will then cause all of the children to be rendered,
 rather than just the one that matches the conditional.
parent 6d2cd987
...@@ -231,9 +231,10 @@ def xblock_view_handler(request, package_id, view_name, tag=None, branch=None, v ...@@ -231,9 +231,10 @@ def xblock_view_handler(request, package_id, view_name, tag=None, branch=None, v
# with the new container view. # with the new container view.
is_read_only_view = is_container_view is_read_only_view = is_container_view
context = { context = {
'runtime_type': 'studio',
'container_view': is_container_view, 'container_view': is_container_view,
'read_only': is_read_only_view, 'read_only': is_read_only_view,
'root_xblock': component 'root_xblock': component,
} }
fragment = get_preview_fragment(request, component, context) fragment = get_preview_fragment(request, component, context)
......
...@@ -157,6 +157,22 @@ class GetItem(ItemTest): ...@@ -157,6 +157,22 @@ class GetItem(ItemTest):
'<span class="action-button-text">View</span>') '<span class="action-button-text">View</span>')
) )
def test_split_test(self):
"""
Test that a split_test module renders all of its children in Studio.
"""
root_locator = self._create_vertical()
resp = self.create_xblock(category='split_test', parent_locator=root_locator)
self.assertEqual(resp.status_code, 200)
split_test_locator = self.response_locator(resp)
resp = self.create_xblock(parent_locator=split_test_locator, category='html', boilerplate='announcement.yaml')
self.assertEqual(resp.status_code, 200)
resp = self.create_xblock(parent_locator=split_test_locator, category='html', boilerplate='zooming_image.yaml')
self.assertEqual(resp.status_code, 200)
html, __ = self._get_container_preview(split_test_locator)
self.assertIn('Announcement', html)
self.assertIn('Zooming', html)
class DeleteItem(ItemTest): class DeleteItem(ItemTest):
"""Tests for '/xblock' DELETE url.""" """Tests for '/xblock' DELETE url."""
......
...@@ -41,7 +41,7 @@ class SplitTestFields(object): ...@@ -41,7 +41,7 @@ class SplitTestFields(object):
@XBlock.needs('user_tags') # pylint: disable=abstract-method @XBlock.needs('user_tags') # pylint: disable=abstract-method
@XBlock.needs('partitions') @XBlock.wants('partitions')
class SplitTestModule(SplitTestFields, XModule): class SplitTestModule(SplitTestFields, XModule):
""" """
Show the user the appropriate child. Uses the ExperimentState Show the user the appropriate child. Uses the ExperimentState
...@@ -61,7 +61,10 @@ class SplitTestModule(SplitTestFields, XModule): ...@@ -61,7 +61,10 @@ class SplitTestModule(SplitTestFields, XModule):
super(SplitTestModule, self).__init__(*args, **kwargs) super(SplitTestModule, self).__init__(*args, **kwargs)
self.child_descriptor = self.get_child_descriptors()[0] self.child_descriptor = None
child_descriptors = self.get_child_descriptors()
if len(child_descriptors) >= 1:
self.child_descriptor = child_descriptors[0]
if self.child_descriptor is not None: if self.child_descriptor is not None:
self.child = self.system.get_module(self.child_descriptor) self.child = self.system.get_module(self.child_descriptor)
else: else:
...@@ -106,7 +109,9 @@ class SplitTestModule(SplitTestFields, XModule): ...@@ -106,7 +109,9 @@ class SplitTestModule(SplitTestFields, XModule):
""" """
For grading--return just the chosen child. For grading--return just the chosen child.
""" """
group_id = self.runtime.service(self, 'partitions').get_user_group_for_partition(self.user_partition_id) group_id = self.get_group_id()
if group_id is None:
return []
# group_id_to_child comes from json, so it has to have string keys # group_id_to_child comes from json, so it has to have string keys
str_group_id = str(group_id) str_group_id = str(group_id)
...@@ -126,6 +131,15 @@ class SplitTestModule(SplitTestFields, XModule): ...@@ -126,6 +131,15 @@ class SplitTestModule(SplitTestFields, XModule):
return [child_descriptor] return [child_descriptor]
def get_group_id(self):
"""
Returns the group ID, or None if none is available.
"""
partitions_service = self.runtime.service(self, 'partitions')
if not partitions_service:
return None
return partitions_service.get_user_group_for_partition(self.user_partition_id)
def _staff_view(self, context): def _staff_view(self, context):
""" """
Render the staff view for a split test module. Render the staff view for a split test module.
...@@ -155,11 +169,37 @@ class SplitTestModule(SplitTestFields, XModule): ...@@ -155,11 +169,37 @@ class SplitTestModule(SplitTestFields, XModule):
fragment.initialize_js('ABTestSelector') fragment.initialize_js('ABTestSelector')
return fragment return fragment
def studio_preview_view(self, context):
"""
Renders the Studio preview by rendering each child so that they can all be seen and edited.
"""
fragment = Fragment()
contents = []
for child in self.descriptor.get_children():
rendered_child = self.runtime.get_module(child).render('student_view', context)
fragment.add_frag_resources(rendered_child)
contents.append({
'id': child.id,
'content': rendered_child.content
})
fragment.add_content(self.system.render_template('vert_module.html', {
'items': contents
}))
return fragment
def student_view(self, context): def student_view(self, context):
""" """
Render the contents of the chosen condition for students, and all the Render the contents of the chosen condition for students, and all the
conditions for staff. conditions for staff.
""" """
# When rendering a Studio preview, render all of the block's children
if context and context['runtime_type'] == 'studio':
return self.studio_preview_view(context)
if self.child is None: if self.child is None:
# raise error instead? In fact, could complain on descriptor load... # raise error instead? In fact, could complain on descriptor load...
return Fragment(content=u"<div>Nothing here. Move along.</div>") return Fragment(content=u"<div>Nothing here. Move along.</div>")
...@@ -197,7 +237,7 @@ class SplitTestModule(SplitTestFields, XModule): ...@@ -197,7 +237,7 @@ class SplitTestModule(SplitTestFields, XModule):
@XBlock.needs('user_tags') # pylint: disable=abstract-method @XBlock.needs('user_tags') # pylint: disable=abstract-method
@XBlock.needs('partitions') @XBlock.wants('partitions')
class SplitTestDescriptor(SplitTestFields, SequenceDescriptor): class SplitTestDescriptor(SplitTestFields, SequenceDescriptor):
# the editing interface can be the same as for sequences -- just a container # the editing interface can be the same as for sequences -- just a container
module_class = SplitTestModule module_class = SplitTestModule
......
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