@@ -507,6 +507,39 @@ class CoursewareMultipleVerticalsTest(UniqueCourseTest, EventsTestMixin):
|
||||
sequence_ui_events
|
||||
)
|
||||
|
||||
def test_accordion_events(self):
|
||||
self.course_nav.go_to_section('Test Section 1', 'Test Subsection 1,2')
|
||||
|
||||
self.course_nav.go_to_section('Test Section 2', 'Test Subsection 2,1')
|
||||
|
||||
# test UI events emitted by navigating via the course outline
|
||||
filter_outline_ui_event = lambda event: event.get('name', '') == 'edx.ui.lms.outline.selected'
|
||||
|
||||
outline_ui_events = self.wait_for_events(event_filter=filter_outline_ui_event, timeout=2)
|
||||
|
||||
# note: target_url is tested in unit tests, as the url changes here with every test (it includes GUIDs).
|
||||
self.assert_events_match(
|
||||
[
|
||||
{
|
||||
'event_type': 'edx.ui.lms.outline.selected',
|
||||
'name': 'edx.ui.lms.outline.selected',
|
||||
'event': {
|
||||
'target_name': 'Test Subsection 1,2 ',
|
||||
'widget_placement': 'accordion',
|
||||
}
|
||||
},
|
||||
{
|
||||
'event_type': 'edx.ui.lms.outline.selected',
|
||||
'name': 'edx.ui.lms.outline.selected',
|
||||
'event': {
|
||||
'target_name': 'Test Subsection 2,1 ',
|
||||
'widget_placement': 'accordion',
|
||||
}
|
||||
},
|
||||
],
|
||||
outline_ui_events
|
||||
)
|
||||
|
||||
def assert_navigation_state(
|
||||
self, section_title, subsection_title, subsection_position, next_enabled, prev_enabled
|
||||
):
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
Tests courseware views.py
|
||||
"""
|
||||
|
||||
from urllib import urlencode
|
||||
from urllib import urlencode, quote
|
||||
import ddt
|
||||
import json
|
||||
import itertools
|
||||
@@ -191,19 +191,25 @@ class ViewsTestCase(ModuleStoreTestCase):
|
||||
"""
|
||||
Tests for views.py methods.
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
super(ViewsTestCase, self).setUp()
|
||||
self.course = CourseFactory.create(display_name=u'teꜱᴛ course')
|
||||
self.chapter = ItemFactory.create(category='chapter', parent_location=self.course.location)
|
||||
self.chapter = ItemFactory.create(
|
||||
category='chapter',
|
||||
parent_location=self.course.location,
|
||||
display_name="Chapter 1",
|
||||
)
|
||||
self.section = ItemFactory.create(
|
||||
category='sequential',
|
||||
parent_location=self.chapter.location,
|
||||
due=datetime(2013, 9, 18, 11, 30, 00),
|
||||
display_name='Sequential 1',
|
||||
)
|
||||
self.vertical = ItemFactory.create(
|
||||
category='vertical',
|
||||
parent_location=self.section.location,
|
||||
display_name='Vertical 1'
|
||||
display_name='Vertical 1',
|
||||
)
|
||||
self.problem = ItemFactory.create(
|
||||
category='problem',
|
||||
@@ -213,12 +219,13 @@ class ViewsTestCase(ModuleStoreTestCase):
|
||||
|
||||
self.section2 = ItemFactory.create(
|
||||
category='sequential',
|
||||
parent_location=self.chapter.location
|
||||
parent_location=self.chapter.location,
|
||||
display_name='Sequential 2',
|
||||
)
|
||||
self.vertical2 = ItemFactory.create(
|
||||
category='vertical',
|
||||
parent_location=self.section2.location,
|
||||
display_name='Vertical 2'
|
||||
display_name='Vertical 2',
|
||||
)
|
||||
self.problem2 = ItemFactory.create(
|
||||
category='problem',
|
||||
@@ -240,6 +247,12 @@ class ViewsTestCase(ModuleStoreTestCase):
|
||||
self.org = u"ꜱᴛᴀʀᴋ ɪɴᴅᴜꜱᴛʀɪᴇꜱ"
|
||||
self.org_html = "<p>'+Stark/Industries+'</p>"
|
||||
|
||||
self.request = self.request_factory.get("foo")
|
||||
self.request.user = self.user
|
||||
|
||||
# refresh the course from the modulestore so that it has children
|
||||
self.course = modulestore().get_course(self.course.id)
|
||||
|
||||
def test_index_success(self):
|
||||
response = self._verify_index_response()
|
||||
self.assertIn(unicode(self.problem2.location), response.content.decode("utf-8"))
|
||||
@@ -787,6 +800,33 @@ class ViewsTestCase(ModuleStoreTestCase):
|
||||
response = views.course_info(request, course_id)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
def test_accordion(self):
|
||||
table_of_contents = toc_for_course(
|
||||
self.request.user,
|
||||
self.request,
|
||||
self.course,
|
||||
unicode(self.course.get_children()[0].scope_ids.usage_id),
|
||||
None,
|
||||
None
|
||||
)
|
||||
|
||||
# removes newlines and whitespace from the returned view string
|
||||
view = ''.join(render_accordion(self.request, self.course, table_of_contents['chapters']).split())
|
||||
# the course id unicode is re-encoded here because the quote function does not accept unicode
|
||||
course_id = quote(unicode(self.course.id).encode("utf-8"))
|
||||
|
||||
self.assertIn(
|
||||
u'href="/courses/{}/courseware/Chapter_1/Sequential_1/"><pclass="accordion-display-name">Sequential1</p>'
|
||||
.format(course_id.decode("utf-8")),
|
||||
view
|
||||
)
|
||||
|
||||
self.assertIn(
|
||||
u'href="/courses/{}/courseware/Chapter_1/Sequential_2/"><pclass="accordion-display-name">Sequential2</p>'
|
||||
.format(course_id.decode("utf-8")),
|
||||
view
|
||||
)
|
||||
|
||||
|
||||
@attr('shard_1')
|
||||
# setting TIME_ZONE_DISPLAYED_FOR_DEADLINES explicitly
|
||||
@@ -809,7 +849,11 @@ class BaseDueDateTests(ModuleStoreTestCase):
|
||||
"""
|
||||
course = CourseFactory.create(**course_kwargs)
|
||||
chapter = ItemFactory.create(category='chapter', parent_location=course.location)
|
||||
section = ItemFactory.create(category='sequential', parent_location=chapter.location, due=datetime(2013, 9, 18, 11, 30, 00))
|
||||
section = ItemFactory.create(
|
||||
category='sequential',
|
||||
parent_location=chapter.location,
|
||||
due=datetime(2013, 9, 18, 11, 30, 00)
|
||||
)
|
||||
vertical = ItemFactory.create(category='vertical', parent_location=section.location)
|
||||
ItemFactory.create(category='problem', parent_location=vertical.location)
|
||||
|
||||
@@ -1028,7 +1072,6 @@ class ProgressPageTests(ModuleStoreTestCase):
|
||||
'azU3N_8$',
|
||||
]
|
||||
for invalid_id in invalid_student_ids:
|
||||
|
||||
self.assertRaises(
|
||||
Http404, views.progress,
|
||||
self.request,
|
||||
@@ -1117,7 +1160,7 @@ class ProgressPageTests(ModuleStoreTestCase):
|
||||
# Enable certificate generation for this course
|
||||
certs_api.set_cert_generation_enabled(self.course.id, True)
|
||||
|
||||
#course certificate configurations
|
||||
# Course certificate configurations
|
||||
certificates = [
|
||||
{
|
||||
'id': 1,
|
||||
@@ -1324,7 +1367,7 @@ class GenerateUserCertTests(ModuleStoreTestCase):
|
||||
resp = self.client.post(self.url)
|
||||
self.assertEqual(resp.status_code, 200)
|
||||
|
||||
#Verify Google Analytics event fired after generating certificate
|
||||
# Verify Google Analytics event fired after generating certificate
|
||||
mock_tracker.track.assert_called_once_with( # pylint: disable=no-member
|
||||
self.student.id, # pylint: disable=no-member
|
||||
'edx.bi.user.certificate.generate',
|
||||
@@ -1335,8 +1378,7 @@ class GenerateUserCertTests(ModuleStoreTestCase):
|
||||
|
||||
context={
|
||||
'ip': '127.0.0.1',
|
||||
'Google Analytics':
|
||||
{'clientId': None}
|
||||
'Google Analytics': {'clientId': None}
|
||||
}
|
||||
)
|
||||
mock_tracker.reset_mock()
|
||||
@@ -1521,6 +1563,7 @@ class TestIndexViewWithGating(ModuleStoreTestCase, MilestonesTestCaseMixin):
|
||||
"""
|
||||
Test the index view for a course with gated content
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
"""
|
||||
Set up the initial test data
|
||||
@@ -1574,6 +1617,7 @@ class TestRenderXBlock(RenderXBlockTestMixin, ModuleStoreTestCase):
|
||||
This class overrides the get_response method, which is used by
|
||||
the tests defined in RenderXBlockTestMixin.
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
reload_django_url_config()
|
||||
super(TestRenderXBlock, self).setUp()
|
||||
|
||||
@@ -1664,6 +1664,7 @@ REQUIRE_JS_PATH_OVERRIDES = {
|
||||
'moment': 'js/vendor/moment.min.js',
|
||||
'jquery.url': 'js/vendor/url.min.js',
|
||||
'js/courseware/course_home_events': 'js/courseware/course_home_events.js',
|
||||
'js/courseware/accordion_events': 'js/courseware/accordion_events.js',
|
||||
'js/courseware/toggle_element_visibility': 'js/courseware/toggle_element_visibility.js',
|
||||
'js/student_account/logistration_factory': 'js/student_account/logistration_factory.js',
|
||||
'js/student_profile/views/learner_profile_factory': 'js/student_profile/views/learner_profile_factory.js',
|
||||
|
||||
20
lms/static/js/courseware/accordion_events.js
Normal file
20
lms/static/js/courseware/accordion_events.js
Normal file
@@ -0,0 +1,20 @@
|
||||
;(function(define) {
|
||||
'use strict';
|
||||
|
||||
define(['jquery', 'logger'], function ($, Logger) {
|
||||
return function () {
|
||||
$(".accordion-nav").click(function(event) {
|
||||
Logger.log(
|
||||
"edx.ui.lms.outline.selected",
|
||||
{
|
||||
name: "edx.ui.lms.outline.selected",
|
||||
event_type: "edx.ui.lms.outline.selected",
|
||||
current_url: window.location.href,
|
||||
target_url: event.currentTarget.href,
|
||||
target_name: $(this).find("p.accordion-display-name").text(),
|
||||
widget_placement: "accordion"
|
||||
});
|
||||
});
|
||||
};
|
||||
});
|
||||
}).call(this, define || RequireJS.define);
|
||||
@@ -1,4 +1,5 @@
|
||||
<%page expression_filter="h"/>
|
||||
<%namespace name='static' file='../static_content.html'/>
|
||||
<%!
|
||||
from django.core.urlresolvers import reverse
|
||||
from util.date_utils import get_time_display
|
||||
@@ -26,8 +27,8 @@ else:
|
||||
<div class="chapter-menu">
|
||||
% for section in chapter['sections']:
|
||||
<div class="menu-item ${'active' if 'active' in section and section['active'] else ''} ${'graded' if 'graded' in section and section['graded'] else ''}">
|
||||
<a href="${reverse('courseware_section', args=[course_id, chapter['url_name'], section['url_name']])}">
|
||||
<p>${section['display_name']} ${Text(_('{span_start}current section{span_end}')).format(
|
||||
<a class="accordion-nav" href="${reverse('courseware_section', args=[course_id, chapter['url_name'], section['url_name']])}">
|
||||
<p class="accordion-display-name">${section['display_name']} ${Text(_('{span_start}current section{span_end}')).format(
|
||||
span_start=HTML('<span class="sr">'),
|
||||
span_end=HTML('</span>'),
|
||||
) if 'active' in section and section['active'] else ''}</p>
|
||||
@@ -40,7 +41,7 @@ else:
|
||||
%>
|
||||
|
||||
## There is behavior differences between
|
||||
## rending of sections which have proctoring/timed examinations
|
||||
## rendering of sections which have proctoring/timed examinations
|
||||
## and those that do not.
|
||||
##
|
||||
## Proctoring exposes a exam status message field as well as
|
||||
@@ -80,3 +81,10 @@ else:
|
||||
% for chapter in toc:
|
||||
${make_chapter(chapter)}
|
||||
% endfor
|
||||
|
||||
|
||||
% if toc:
|
||||
<%static:require_module module_name="js/courseware/accordion_events" class_name="AccordionEvents">
|
||||
AccordionEvents();
|
||||
</%static:require_module>
|
||||
% endif
|
||||
|
||||
Reference in New Issue
Block a user