Commit adcf4a98 by sanfordstudent

Merge pull request #12038 from edx/sstudent/seq_item_title_

Displaying title of item in course sequence tooltip instead of list of item's children
parents b2dace80 bbcec0cf
...@@ -217,13 +217,9 @@ class SequenceModule(SequenceFields, ProctoringFields, XModule): ...@@ -217,13 +217,9 @@ class SequenceModule(SequenceFields, ProctoringFields, XModule):
rendered_child = child.render(STUDENT_VIEW, context) rendered_child = child.render(STUDENT_VIEW, context)
fragment.add_frag_resources(rendered_child) fragment.add_frag_resources(rendered_child)
# `titles` is a list of titles to inject into the sequential tooltip display.
# We omit any blank titles to avoid blank lines in the tooltip display.
titles = [title.strip() for title in child.get_content_titles() if title.strip()]
childinfo = { childinfo = {
'content': rendered_child.content, 'content': rendered_child.content,
'title': "\n".join(titles), 'page_title': getattr(child, 'tooltip_title', ''),
'page_title': titles[0] if titles else '',
'progress_status': Progress.to_js_status_str(progress), 'progress_status': Progress.to_js_status_str(progress),
'progress_detail': Progress.to_js_detail_str(progress), 'progress_detail': Progress.to_js_detail_str(progress),
'type': child.get_icon_class(), 'type': child.get_icon_class(),
...@@ -231,8 +227,7 @@ class SequenceModule(SequenceFields, ProctoringFields, XModule): ...@@ -231,8 +227,7 @@ class SequenceModule(SequenceFields, ProctoringFields, XModule):
'bookmarked': is_bookmarked, 'bookmarked': is_bookmarked,
'path': " > ".join(display_names + [child.display_name_with_default]), 'path': " > ".join(display_names + [child.display_name_with_default]),
} }
if childinfo['title'] == '':
childinfo['title'] = child.display_name_with_default_escaped
contents.append(childinfo) contents.append(childinfo)
params = { params = {
......
...@@ -356,6 +356,10 @@ class SplitTestModule(SplitTestFields, XModule, StudioEditableModule): ...@@ -356,6 +356,10 @@ class SplitTestModule(SplitTestFields, XModule, StudioEditableModule):
return (group.name, group.id) return (group.name, group.id)
return (None, None) return (None, None)
@property
def tooltip_title(self):
return getattr(self.child, 'tooltip_title', '')
def validate(self): def validate(self):
""" """
Message for either error or warning validation message/s. Message for either error or warning validation message/s.
...@@ -695,3 +699,5 @@ class SplitTestDescriptor(SplitTestFields, SequenceDescriptor, StudioEditableDes ...@@ -695,3 +699,5 @@ class SplitTestDescriptor(SplitTestFields, SequenceDescriptor, StudioEditableDes
) )
self.children.append(dest_usage_key) # pylint: disable=no-member self.children.append(dest_usage_key) # pylint: disable=no-member
self.group_id_to_child[unicode(group.id)] = dest_usage_key self.group_id_to_child[unicode(group.id)] = dest_usage_key
tooltip_title = module_attr('tooltip_title')
...@@ -161,3 +161,8 @@ class SequenceBlockTestCase(XModuleXmlImportTest): ...@@ -161,3 +161,8 @@ class SequenceBlockTestCase(XModuleXmlImportTest):
lambda course_key, block_location, child: block_location, lambda course_key, block_location, child: block_location,
) )
self.assertEquals(actual_next_sequence_location, expected_prev_sequence_location) self.assertEquals(actual_next_sequence_location, expected_prev_sequence_location)
def test_tooltip(self):
html = self._get_rendered_student_view(self.sequence_3_1, requested_child=None)
for child in self.sequence_3_1.children:
self.assertIn("'page_title': '{}'".format(child.name), html)
...@@ -366,6 +366,13 @@ class XModuleMixin(XModuleFields, XBlock): ...@@ -366,6 +366,13 @@ class XModuleMixin(XModuleFields, XBlock):
return course_metadata_utils.display_name_with_default_escaped(self) return course_metadata_utils.display_name_with_default_escaped(self)
@property @property
def tooltip_title(self):
"""
Return the title for the sequence item containing this xmodule as its top level item.
"""
return self.display_name_with_default
@property
def xblock_kvs(self): def xblock_kvs(self):
""" """
Retrieves the internal KeyValueStore for this XModule. Retrieves the internal KeyValueStore for this XModule.
......
...@@ -103,20 +103,20 @@ class CourseNavPage(PageObject): ...@@ -103,20 +103,20 @@ class CourseNavPage(PageObject):
self.q(css=subsection_css).first.click() self.q(css=subsection_css).first.click()
self._on_section_promise(section_title, subsection_title).fulfill() self._on_section_promise(section_title, subsection_title).fulfill()
def go_to_sequential(self, sequential_title): def go_to_vertical(self, vertical_title):
""" """
Within a section/subsection, navigate to the sequential with `sequential_title`. Within a section/subsection, navigate to the vertical with `vertical_title`.
""" """
# Get the index of the item in the sequence # Get the index of the item in the sequence
all_items = self.sequence_items all_items = self.sequence_items
try: try:
seq_index = all_items.index(sequential_title) seq_index = all_items.index(vertical_title)
except ValueError: except ValueError:
msg = "Could not find sequential '{0}'. Available sequentials: [{1}]".format( msg = "Could not find sequential '{0}'. Available sequentials: [{1}]".format(
sequential_title, ", ".join(all_items) vertical_title, ", ".join(all_items)
) )
self.warning(msg) self.warning(msg)
......
...@@ -212,7 +212,7 @@ class CertificateProgressPageTest(UniqueCourseTest): ...@@ -212,7 +212,7 @@ class CertificateProgressPageTest(UniqueCourseTest):
self.course_nav.go_to_section('Test Section', 'Test Subsection') self.course_nav.go_to_section('Test Section', 'Test Subsection')
# Navigate to Test Problem 1 # Navigate to Test Problem 1
self.course_nav.go_to_sequential('Test Problem 1') self.course_nav.go_to_vertical('Test Problem 1')
# Select correct value for from select menu # Select correct value for from select menu
self.course_nav.q(css='select option[value="{}"]'.format('blue')).first.click() self.course_nav.q(css='select option[value="{}"]'.format('blue')).first.click()
...@@ -232,7 +232,7 @@ class CertificateProgressPageTest(UniqueCourseTest): ...@@ -232,7 +232,7 @@ class CertificateProgressPageTest(UniqueCourseTest):
self.course_nav.go_to_section('Test Section 2', 'Test Subsection 2') self.course_nav.go_to_section('Test Section 2', 'Test Subsection 2')
# Navigate to Test Problem 2 # Navigate to Test Problem 2
self.course_nav.go_to_sequential('Test Problem 2') self.course_nav.go_to_vertical('Test Problem 2')
# Fill in the answer of the problem # Fill in the answer of the problem
self.course_nav.q(css='input[id^=input_][id$=_2_1]').fill('A*x^2 + sqrt(y)') self.course_nav.q(css='input[id^=input_][id$=_2_1]').fill('A*x^2 + sqrt(y)')
......
...@@ -824,13 +824,13 @@ class VisibleToStaffOnlyTest(UniqueCourseTest): ...@@ -824,13 +824,13 @@ class VisibleToStaffOnlyTest(UniqueCourseTest):
self.assertEqual(3, len(self.course_nav.sections['Test Section'])) self.assertEqual(3, len(self.course_nav.sections['Test Section']))
self.course_nav.go_to_section("Test Section", "Subsection With Locked Unit") self.course_nav.go_to_section("Test Section", "Subsection With Locked Unit")
self.assertEqual(["Html Child in locked unit", "Html Child in unlocked unit"], self.course_nav.sequence_items) self.assertEqual([u'Locked Unit', u'Unlocked Unit'], self.course_nav.sequence_items)
self.course_nav.go_to_section("Test Section", "Unlocked Subsection") self.course_nav.go_to_section("Test Section", "Unlocked Subsection")
self.assertEqual(["Html Child in visible unit"], self.course_nav.sequence_items) self.assertEqual([u'Test Unit'], self.course_nav.sequence_items)
self.course_nav.go_to_section("Test Section", "Locked Subsection") self.course_nav.go_to_section("Test Section", "Locked Subsection")
self.assertEqual(["Html Child in locked subsection"], self.course_nav.sequence_items) self.assertEqual([u'Test Unit'], self.course_nav.sequence_items)
def test_visible_to_student(self): def test_visible_to_student(self):
""" """
...@@ -846,10 +846,10 @@ class VisibleToStaffOnlyTest(UniqueCourseTest): ...@@ -846,10 +846,10 @@ class VisibleToStaffOnlyTest(UniqueCourseTest):
self.assertEqual(2, len(self.course_nav.sections['Test Section'])) self.assertEqual(2, len(self.course_nav.sections['Test Section']))
self.course_nav.go_to_section("Test Section", "Subsection With Locked Unit") self.course_nav.go_to_section("Test Section", "Subsection With Locked Unit")
self.assertEqual(["Html Child in unlocked unit"], self.course_nav.sequence_items) self.assertEqual([u'Unlocked Unit'], self.course_nav.sequence_items)
self.course_nav.go_to_section("Test Section", "Unlocked Subsection") self.course_nav.go_to_section("Test Section", "Unlocked Subsection")
self.assertEqual(["Html Child in visible unit"], self.course_nav.sequence_items) self.assertEqual([u'Test Unit'], self.course_nav.sequence_items)
@attr('shard_1') @attr('shard_1')
......
...@@ -63,7 +63,7 @@ class VideoBaseTest(UniqueCourseTest): ...@@ -63,7 +63,7 @@ class VideoBaseTest(UniqueCourseTest):
self.metadata = None self.metadata = None
self.assets = [] self.assets = []
self.verticals = None self.contents_of_verticals = None
self.youtube_configuration = {} self.youtube_configuration = {}
self.user_info = {} self.user_info = {}
...@@ -104,28 +104,28 @@ class VideoBaseTest(UniqueCourseTest): ...@@ -104,28 +104,28 @@ class VideoBaseTest(UniqueCourseTest):
:return: a list of XBlockFixtureDesc :return: a list of XBlockFixtureDesc
""" """
xblock_verticals = [] xblock_verticals = []
_verticals = self.verticals _contents_of_verticals = self.contents_of_verticals
# Video tests require at least one vertical with a single video. # Video tests require at least one vertical with a single video.
if not _verticals: if not _contents_of_verticals:
_verticals = [[{'display_name': 'Video', 'metadata': self.metadata}]] _contents_of_verticals = [[{'display_name': 'Video', 'metadata': self.metadata}]]
for vertical_index, vertical in enumerate(_verticals): for vertical_index, vertical in enumerate(_contents_of_verticals):
xblock_verticals.append(self._create_single_vertical(vertical, vertical_index)) xblock_verticals.append(self._create_single_vertical(vertical, vertical_index))
return xblock_verticals return xblock_verticals
def _create_single_vertical(self, vertical, vertical_index): def _create_single_vertical(self, vertical_contents, vertical_index):
""" """
Create a single course vertical of type XBlockFixtureDesc with category `vertical`. Create a single course vertical of type XBlockFixtureDesc with category `vertical`.
A single course vertical can contain single or multiple video modules. A single course vertical can contain single or multiple video modules.
:param vertical: vertical data list :param vertical_contents: a list of items for the vertical to contain
:param vertical_index: index for the vertical display name :param vertical_index: index for the vertical display name
:return: XBlockFixtureDesc :return: XBlockFixtureDesc
""" """
xblock_course_vertical = XBlockFixtureDesc('vertical', 'Test Vertical-{0}'.format(vertical_index)) xblock_course_vertical = XBlockFixtureDesc('vertical', 'Test Vertical-{0}'.format(vertical_index))
for video in vertical: for video in vertical_contents:
xblock_course_vertical.add_children( xblock_course_vertical.add_children(
XBlockFixtureDesc('video', video['display_name'], metadata=video.get('metadata'))) XBlockFixtureDesc('video', video['display_name'], metadata=video.get('metadata')))
...@@ -514,13 +514,13 @@ class YouTubeVideoTest(VideoBaseTest): ...@@ -514,13 +514,13 @@ class YouTubeVideoTest(VideoBaseTest):
data_c = {'track': 'http://example.org/', 'download_track': True} data_c = {'track': 'http://example.org/', 'download_track': True}
html5_c_metadata = self.metadata_for_mode('html5', additional_data=data_c) html5_c_metadata = self.metadata_for_mode('html5', additional_data=data_c)
self.verticals = [ self.contents_of_verticals = [
[{'display_name': 'A', 'metadata': youtube_a_metadata}], [{'display_name': 'A', 'metadata': youtube_a_metadata}],
[{'display_name': 'B', 'metadata': youtube_b_metadata}], [{'display_name': 'B', 'metadata': youtube_b_metadata}],
[{'display_name': 'C', 'metadata': html5_c_metadata}] [{'display_name': 'C', 'metadata': html5_c_metadata}]
] ]
# open the section with videos (open video "A") # open the section with videos (open vertical containing video "A")
self.navigate_to_video() self.navigate_to_video()
# check if we can download transcript in "srt" format that has text "00:00:00,260" # check if we can download transcript in "srt" format that has text "00:00:00,260"
...@@ -532,14 +532,14 @@ class YouTubeVideoTest(VideoBaseTest): ...@@ -532,14 +532,14 @@ class YouTubeVideoTest(VideoBaseTest):
# check if we can download transcript in "txt" format that has text "Welcome to edX." # check if we can download transcript in "txt" format that has text "Welcome to edX."
self.assertTrue(self.video.downloaded_transcript_contains_text('txt', 'Welcome to edX.')) self.assertTrue(self.video.downloaded_transcript_contains_text('txt', 'Welcome to edX.'))
# open video "B" # open vertical containing video "B"
self.course_nav.go_to_sequential('B') self.course_nav.go_to_vertical('Test Vertical-1')
# check if we can download transcript in "txt" format that has text "Equal transcripts" # check if we can download transcript in "txt" format that has text "Equal transcripts"
self.assertTrue(self.video.downloaded_transcript_contains_text('txt', 'Equal transcripts')) self.assertTrue(self.video.downloaded_transcript_contains_text('txt', 'Equal transcripts'))
# open video "C" # open vertical containing video "C"
self.course_nav.go_to_sequential('C') self.course_nav.go_to_vertical('Test Vertical-2')
# menu "download_transcript" doesn't exist # menu "download_transcript" doesn't exist
self.assertFalse(self.video.is_menu_present('download_transcript')) self.assertFalse(self.video.is_menu_present('download_transcript'))
...@@ -637,7 +637,7 @@ class YouTubeVideoTest(VideoBaseTest): ...@@ -637,7 +637,7 @@ class YouTubeVideoTest(VideoBaseTest):
Given it has videos "A,B" in "Youtube" mode in position "1" of sequential Given it has videos "A,B" in "Youtube" mode in position "1" of sequential
And videos "C,D" in "Youtube" mode in position "2" of sequential And videos "C,D" in "Youtube" mode in position "2" of sequential
""" """
self.verticals = [ self.contents_of_verticals = [
[{'display_name': 'A'}, {'display_name': 'B'}], [{'display_name': 'A'}, {'display_name': 'B'}],
[{'display_name': 'C'}, {'display_name': 'D'}] [{'display_name': 'C'}, {'display_name': 'D'}]
] ]
...@@ -677,7 +677,9 @@ class YouTubeVideoTest(VideoBaseTest): ...@@ -677,7 +677,9 @@ class YouTubeVideoTest(VideoBaseTest):
And a video "B" in "Youtube" mode in position "2" of sequential And a video "B" in "Youtube" mode in position "2" of sequential
And a video "C" in "HTML5" mode in position "3" of sequential And a video "C" in "HTML5" mode in position "3" of sequential
""" """
self.verticals = [ # vertical titles are created in VideoBaseTest._create_single_vertical
# and are of the form Test Vertical-{_} where _ is the index in self.contents_of_verticals
self.contents_of_verticals = [
[{'display_name': 'A'}], [{'display_name': 'B'}], [{'display_name': 'A'}], [{'display_name': 'B'}],
[{'display_name': 'C', 'metadata': self.metadata_for_mode('html5')}] [{'display_name': 'C', 'metadata': self.metadata_for_mode('html5')}]
] ]
...@@ -685,17 +687,17 @@ class YouTubeVideoTest(VideoBaseTest): ...@@ -685,17 +687,17 @@ class YouTubeVideoTest(VideoBaseTest):
self.navigate_to_video() self.navigate_to_video()
# select the "2.0" speed on video "A" # select the "2.0" speed on video "A"
self.course_nav.go_to_sequential('A') self.course_nav.go_to_vertical('Test Vertical-0')
self.video.wait_for_video_player_render() self.video.wait_for_video_player_render()
self.video.speed = '2.0' self.video.speed = '2.0'
# select the "0.50" speed on video "B" # select the "0.50" speed on video "B"
self.course_nav.go_to_sequential('B') self.course_nav.go_to_vertical('Test Vertical-1')
self.video.wait_for_video_player_render() self.video.wait_for_video_player_render()
self.video.speed = '0.50' self.video.speed = '0.50'
# open video "C" # open video "C"
self.course_nav.go_to_sequential('C') self.course_nav.go_to_vertical('Test Vertical-2')
self.video.wait_for_video_player_render() self.video.wait_for_video_player_render()
# Since the playback speed was set to .5 in "B", this video will also be impacted # Since the playback speed was set to .5 in "B", this video will also be impacted
...@@ -703,8 +705,8 @@ class YouTubeVideoTest(VideoBaseTest): ...@@ -703,8 +705,8 @@ class YouTubeVideoTest(VideoBaseTest):
# does not have a .5 playback option, so the closest possible (.75) should be selected. # does not have a .5 playback option, so the closest possible (.75) should be selected.
self.video.verify_speed_changed('0.75x') self.video.verify_speed_changed('0.75x')
# open video "A" # go to the vertical containing video "A"
self.course_nav.go_to_sequential('A') self.course_nav.go_to_vertical('Test Vertical-0')
# Video "A" should still play at speed 2.0 because it was explicitly set to that. # Video "A" should still play at speed 2.0 because it was explicitly set to that.
self.assertEqual(self.video.speed, '2.0x') self.assertEqual(self.video.speed, '2.0x')
...@@ -712,8 +714,8 @@ class YouTubeVideoTest(VideoBaseTest): ...@@ -712,8 +714,8 @@ class YouTubeVideoTest(VideoBaseTest):
# reload the page # reload the page
self.video.reload_page() self.video.reload_page()
# open video "A" # go to the vertical containing video "A"
self.course_nav.go_to_sequential('A') self.course_nav.go_to_vertical('Test Vertical-0')
# check if video "A" should start playing at speed "2.0" # check if video "A" should start playing at speed "2.0"
self.assertEqual(self.video.speed, '2.0x') self.assertEqual(self.video.speed, '2.0x')
...@@ -721,14 +723,14 @@ class YouTubeVideoTest(VideoBaseTest): ...@@ -721,14 +723,14 @@ class YouTubeVideoTest(VideoBaseTest):
# select the "1.0" speed on video "A" # select the "1.0" speed on video "A"
self.video.speed = '1.0' self.video.speed = '1.0'
# open video "B" # go to the vertical containing "B"
self.course_nav.go_to_sequential('B') self.course_nav.go_to_vertical('Test Vertical-1')
# Video "B" should still play at speed .5 because it was explicitly set to that. # Video "B" should still play at speed .5 because it was explicitly set to that.
self.assertEqual(self.video.speed, '0.50x') self.assertEqual(self.video.speed, '0.50x')
# open video "C" # go to the vertical containing video "C"
self.course_nav.go_to_sequential('C') self.course_nav.go_to_vertical('Test Vertical-2')
# The change of speed for Video "A" should impact Video "C" because it still has # The change of speed for Video "A" should impact Video "C" because it still has
# not been explicitly set to a speed. # not been explicitly set to a speed.
...@@ -884,7 +886,7 @@ class YouTubeVideoTest(VideoBaseTest): ...@@ -884,7 +886,7 @@ class YouTubeVideoTest(VideoBaseTest):
} }
} }
self.verticals = [ self.contents_of_verticals = [
[{'display_name': 'A'}, {'display_name': 'B', 'metadata': self.metadata_for_mode('html5')}], [{'display_name': 'A'}, {'display_name': 'B', 'metadata': self.metadata_for_mode('html5')}],
[{'display_name': 'C'}] [{'display_name': 'C'}]
] ]
......
...@@ -255,8 +255,7 @@ class EntranceExamTestCases(LoginEnrollmentTestCase, ModuleStoreTestCase, Milest ...@@ -255,8 +255,7 @@ class EntranceExamTestCases(LoginEnrollmentTestCase, ModuleStoreTestCase, Milest
resp = self.client.get(url) resp = self.client.get(url)
self.assertRedirects(resp, expected_url, status_code=302, target_status_code=200) self.assertRedirects(resp, expected_url, status_code=302, target_status_code=200)
resp = self.client.get(expected_url) resp = self.client.get(expected_url)
self.assertNotIn('Exam Problem - Problem 1', resp.content) self.assertNotIn('Exam Vertical - Unit 1', resp.content)
self.assertNotIn('Exam Problem - Problem 2', resp.content)
def test_entrance_exam_content_presence(self): def test_entrance_exam_content_presence(self):
""" """
...@@ -273,8 +272,7 @@ class EntranceExamTestCases(LoginEnrollmentTestCase, ModuleStoreTestCase, Milest ...@@ -273,8 +272,7 @@ class EntranceExamTestCases(LoginEnrollmentTestCase, ModuleStoreTestCase, Milest
resp = self.client.get(url) resp = self.client.get(url)
self.assertRedirects(resp, expected_url, status_code=302, target_status_code=200) self.assertRedirects(resp, expected_url, status_code=302, target_status_code=200)
resp = self.client.get(expected_url) resp = self.client.get(expected_url)
self.assertIn('Exam Problem - Problem 1', resp.content) self.assertIn('Exam Vertical - Unit 1', resp.content)
self.assertIn('Exam Problem - Problem 2', resp.content)
def test_get_entrance_exam_content(self): def test_get_entrance_exam_content(self):
""" """
......
...@@ -24,7 +24,6 @@ class SplitTestBase(SharedModuleStoreTestCase): ...@@ -24,7 +24,6 @@ class SplitTestBase(SharedModuleStoreTestCase):
COURSE_NUMBER = 'split-test-base' COURSE_NUMBER = 'split-test-base'
ICON_CLASSES = None ICON_CLASSES = None
TOOLTIPS = None TOOLTIPS = None
HIDDEN_CONTENT = None
VISIBLE_CONTENT = None VISIBLE_CONTENT = None
@classmethod @classmethod
...@@ -63,6 +62,9 @@ class SplitTestBase(SharedModuleStoreTestCase): ...@@ -63,6 +62,9 @@ class SplitTestBase(SharedModuleStoreTestCase):
CourseEnrollmentFactory.create(user=self.student, course_id=self.course.id) CourseEnrollmentFactory.create(user=self.student, course_id=self.course.id)
self.client.login(username=self.student.username, password='test') self.client.login(username=self.student.username, password='test')
self.included_usage_keys = None
self.excluded_usage_keys = None
def _video(self, parent, group): def _video(self, parent, group):
""" """
Returns a video component with parent ``parent`` Returns a video component with parent ``parent``
...@@ -128,35 +130,34 @@ class SplitTestBase(SharedModuleStoreTestCase): ...@@ -128,35 +130,34 @@ class SplitTestBase(SharedModuleStoreTestCase):
for tooltip in self.TOOLTIPS[user_tag]: for tooltip in self.TOOLTIPS[user_tag]:
self.assertIn(tooltip, content) self.assertIn(tooltip, content)
for hidden in self.HIDDEN_CONTENT[user_tag]: unicode_content = content.decode("utf-8")
self.assertNotIn(hidden, content) for key in self.included_usage_keys[user_tag]:
self.assertIn(unicode(key), unicode_content)
for key in self.excluded_usage_keys[user_tag]:
self.assertNotIn(unicode(key), unicode_content)
# Assert that we can see the data from the appropriate test condition # Assert that we can see the data from the appropriate test condition
for visible in self.VISIBLE_CONTENT[user_tag]: for visible in self.VISIBLE_CONTENT[user_tag]:
self.assertIn(visible, content) self.assertIn(visible, content)
class TestVertSplitTestVert(SplitTestBase): class TestSplitTestVert(SplitTestBase):
""" """
Tests related to xmodule/split_test_module Tests a sequential whose top-level vertical is determined by a split test.
""" """
__test__ = True __test__ = True
COURSE_NUMBER = 'vert-split-vert' COURSE_NUMBER = 'test-split-test-vert-vert'
ICON_CLASSES = [ ICON_CLASSES = [
'seq_problem', 'seq_problem',
'seq_video', 'seq_video',
] ]
TOOLTIPS = [ TOOLTIPS = [
['Group 0 Sees This Video', "Group 0 Sees This Problem"],
['Group 1 Sees This Video', 'Group 1 Sees This HTML'],
]
HIDDEN_CONTENT = [
['Condition 0 vertical'], ['Condition 0 vertical'],
['Condition 1 vertical'], ['Condition 1 vertical'],
] ]
# Data is html encoded, because it's inactive inside the # Data is html encoded, because it's inactive inside the
# sequence until javascript is executed # sequence until javascript is executed
VISIBLE_CONTENT = [ VISIBLE_CONTENT = [
...@@ -167,21 +168,13 @@ class TestVertSplitTestVert(SplitTestBase): ...@@ -167,21 +168,13 @@ class TestVertSplitTestVert(SplitTestBase):
def setUp(self): def setUp(self):
# We define problem compenents that we need but don't explicitly call elsewhere. # We define problem compenents that we need but don't explicitly call elsewhere.
# pylint: disable=unused-variable # pylint: disable=unused-variable
super(TestVertSplitTestVert, self).setUp() super(TestSplitTestVert, self).setUp()
# vert <- split_test
# split_test cond 0 = vert <- {video, problem}
# split_test cond 1 = vert <- {video, html}
vert1 = ItemFactory.create(
parent_location=self.sequential.location,
category="vertical",
display_name="Split test vertical",
)
c0_url = self.course.id.make_usage_key("vertical", "split_test_cond0") c0_url = self.course.id.make_usage_key("vertical", "split_test_cond0")
c1_url = self.course.id.make_usage_key("vertical", "split_test_cond1") c1_url = self.course.id.make_usage_key("vertical", "split_test_cond1")
split_test = ItemFactory.create( split_test = ItemFactory.create(
parent_location=vert1.location, parent_location=self.sequential.location,
category="split_test", category="split_test",
display_name="Split test", display_name="Split test",
user_partition_id='0', user_partition_id='0',
...@@ -206,26 +199,32 @@ class TestVertSplitTestVert(SplitTestBase): ...@@ -206,26 +199,32 @@ class TestVertSplitTestVert(SplitTestBase):
video1 = self._video(cond1vert, 1) video1 = self._video(cond1vert, 1)
html1 = self._html(cond1vert, 1) html1 = self._html(cond1vert, 1)
self.included_usage_keys = [
[video0.location, problem0.location],
[video1.location, html1.location],
]
class TestSplitTestVert(SplitTestBase): self.excluded_usage_keys = [
[video1.location, html1.location],
[video0.location, problem0.location],
]
class TestVertSplitTestVert(SplitTestBase):
""" """
Tests related to xmodule/split_test_module Tests a sequential whose top-level vertical contains a split test determining content within that vertical.
""" """
__test__ = True __test__ = True
COURSE_NUMBER = 'split-vert' COURSE_NUMBER = 'test-vert-split-test-vert'
ICON_CLASSES = [ ICON_CLASSES = [
'seq_problem', 'seq_problem',
'seq_video', 'seq_video',
] ]
TOOLTIPS = [ TOOLTIPS = [
['Group 0 Sees This Video', "Group 0 Sees This Problem"], ['Split test vertical'],
['Group 1 Sees This Video', 'Group 1 Sees This HTML'], ['Split test vertical'],
]
HIDDEN_CONTENT = [
['Condition 0 vertical'],
['Condition 1 vertical'],
] ]
# Data is html encoded, because it's inactive inside the # Data is html encoded, because it's inactive inside the
...@@ -238,15 +237,18 @@ class TestSplitTestVert(SplitTestBase): ...@@ -238,15 +237,18 @@ class TestSplitTestVert(SplitTestBase):
def setUp(self): def setUp(self):
# We define problem compenents that we need but don't explicitly call elsewhere. # We define problem compenents that we need but don't explicitly call elsewhere.
# pylint: disable=unused-variable # pylint: disable=unused-variable
super(TestSplitTestVert, self).setUp() super(TestVertSplitTestVert, self).setUp()
# split_test cond 0 = vert <- {video, problem} vert1 = ItemFactory.create(
# split_test cond 1 = vert <- {video, html} parent_location=self.sequential.location,
category="vertical",
display_name="Split test vertical",
)
c0_url = self.course.id.make_usage_key("vertical", "split_test_cond0") c0_url = self.course.id.make_usage_key("vertical", "split_test_cond0")
c1_url = self.course.id.make_usage_key("vertical", "split_test_cond1") c1_url = self.course.id.make_usage_key("vertical", "split_test_cond1")
split_test = ItemFactory.create( split_test = ItemFactory.create(
parent_location=self.sequential.location, parent_location=vert1.location,
category="split_test", category="split_test",
display_name="Split test", display_name="Split test",
user_partition_id='0', user_partition_id='0',
...@@ -256,8 +258,8 @@ class TestSplitTestVert(SplitTestBase): ...@@ -256,8 +258,8 @@ class TestSplitTestVert(SplitTestBase):
cond0vert = ItemFactory.create( cond0vert = ItemFactory.create(
parent_location=split_test.location, parent_location=split_test.location,
category="vertical", category="vertical",
display_name="Condition 0 vertical", display_name="Condition 0 Vertical",
location=c0_url, location=c0_url
) )
video0 = self._video(cond0vert, 0) video0 = self._video(cond0vert, 0)
problem0 = self._problem(cond0vert, 0) problem0 = self._problem(cond0vert, 0)
...@@ -265,12 +267,22 @@ class TestSplitTestVert(SplitTestBase): ...@@ -265,12 +267,22 @@ class TestSplitTestVert(SplitTestBase):
cond1vert = ItemFactory.create( cond1vert = ItemFactory.create(
parent_location=split_test.location, parent_location=split_test.location,
category="vertical", category="vertical",
display_name="Condition 1 vertical", display_name="Condition 1 Vertical",
location=c1_url, location=c1_url
) )
video1 = self._video(cond1vert, 1) video1 = self._video(cond1vert, 1)
html1 = self._html(cond1vert, 1) html1 = self._html(cond1vert, 1)
self.included_usage_keys = [
[video0.location, problem0.location],
[video1.location, html1.location],
]
self.excluded_usage_keys = [
[video1.location, html1.location],
[video0.location, problem0.location],
]
@attr('shard_1') @attr('shard_1')
class SplitTestPosition(SharedModuleStoreTestCase): class SplitTestPosition(SharedModuleStoreTestCase):
......
...@@ -198,16 +198,27 @@ class ViewsTestCase(ModuleStoreTestCase): ...@@ -198,16 +198,27 @@ class ViewsTestCase(ModuleStoreTestCase):
parent_location=self.chapter.location, parent_location=self.chapter.location,
due=datetime(2013, 9, 18, 11, 30, 00), due=datetime(2013, 9, 18, 11, 30, 00),
) )
self.vertical = ItemFactory.create(category='vertical', parent_location=self.section.location) self.vertical = ItemFactory.create(
self.component = ItemFactory.create( category='vertical',
parent_location=self.section.location,
display_name='Vertical 1'
)
self.problem = ItemFactory.create(
category='problem', category='problem',
parent_location=self.vertical.location, parent_location=self.vertical.location,
display_name='Problem 1', display_name='Problem 1',
) )
self.section2 = ItemFactory.create(category='sequential', parent_location=self.chapter.location) self.section2 = ItemFactory.create(
self.vertical2 = ItemFactory.create(category='vertical', parent_location=self.section2.location) category='sequential',
ItemFactory.create( parent_location=self.chapter.location
)
self.vertical2 = ItemFactory.create(
category='vertical',
parent_location=self.section2.location,
display_name='Vertical 2'
)
self.problem2 = ItemFactory.create(
category='problem', category='problem',
parent_location=self.vertical2.location, parent_location=self.vertical2.location,
display_name='Problem 2', display_name='Problem 2',
...@@ -229,15 +240,15 @@ class ViewsTestCase(ModuleStoreTestCase): ...@@ -229,15 +240,15 @@ class ViewsTestCase(ModuleStoreTestCase):
def test_index_success(self): def test_index_success(self):
response = self._verify_index_response() response = self._verify_index_response()
self.assertIn('Problem 2', response.content) self.assertIn(unicode(self.problem2.location), response.content.decode("utf-8"))
# re-access to the main course page redirects to last accessed view. # re-access to the main course page redirects to last accessed view.
url = reverse('courseware', kwargs={'course_id': unicode(self.course_key)}) url = reverse('courseware', kwargs={'course_id': unicode(self.course_key)})
response = self.client.get(url) response = self.client.get(url)
self.assertEqual(response.status_code, 302) self.assertEqual(response.status_code, 302)
response = self.client.get(response.url) # pylint: disable=no-member response = self.client.get(response.url) # pylint: disable=no-member
self.assertNotIn('Problem 1', response.content) self.assertNotIn(unicode(self.problem.location), response.content.decode("utf-8"))
self.assertIn('Problem 2', response.content) self.assertIn(unicode(self.problem2.location), response.content.decode("utf-8"))
def test_index_nonexistent_chapter(self): def test_index_nonexistent_chapter(self):
self._verify_index_response(expected_response_code=404, chapter_name='non-existent') self._verify_index_response(expected_response_code=404, chapter_name='non-existent')
...@@ -540,7 +551,7 @@ class ViewsTestCase(ModuleStoreTestCase): ...@@ -540,7 +551,7 @@ class ViewsTestCase(ModuleStoreTestCase):
url = reverse('submission_history', kwargs={ url = reverse('submission_history', kwargs={
'course_id': unicode(self.course_key), 'course_id': unicode(self.course_key),
'student_username': 'dummy', 'student_username': 'dummy',
'location': unicode(self.component.location), 'location': unicode(self.problem.location),
}) })
response = self.client.get(url) response = self.client.get(url)
# Tests that we do not get an "Invalid x" response when passing correct arguments to view # Tests that we do not get an "Invalid x" response when passing correct arguments to view
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
id="tab_${idx}"> id="tab_${idx}">
<i class="icon fa seq_${item['type']}" aria-hidden="true"></i> <i class="icon fa seq_${item['type']}" aria-hidden="true"></i>
<i class="fa fa-fw fa-bookmark bookmark-icon ${"is-hidden" if not item['bookmarked'] else "bookmarked"}" aria-hidden="true"></i> <i class="fa fa-fw fa-bookmark bookmark-icon ${"is-hidden" if not item['bookmarked'] else "bookmarked"}" aria-hidden="true"></i>
<div class="sequence-tooltip sr"><span class="sr">${item['type']}&nbsp;</span>${item['title']}<span class="sr bookmark-icon-sr">&nbsp;${_("Bookmarked") if item['bookmarked'] else ""}</span></div> <div class="sequence-tooltip sr"><span class="sr">${item['type']}&nbsp;</span>${item['page_title']}<span class="sr bookmark-icon-sr">&nbsp;${_("Bookmarked") if item['bookmarked'] else ""}</span></div>
</button> </button>
</li> </li>
% endfor % endfor
......
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