From d4146e7a1dbe5907b21711cbd46b1c3433521fab Mon Sep 17 00:00:00 2001
From: Sanford Student
Date: Thu, 28 Apr 2016 16:25:50 -0400
Subject: [PATCH] accordion emits event
---
.../tests/lms/test_lms_courseware.py | 33 ++++++++++
lms/djangoapps/courseware/tests/test_views.py | 66 +++++++++++++++----
lms/envs/common.py | 1 +
lms/static/js/courseware/accordion_events.js | 20 ++++++
lms/templates/courseware/accordion.html | 14 +++-
5 files changed, 120 insertions(+), 14 deletions(-)
create mode 100644 lms/static/js/courseware/accordion_events.js
diff --git a/common/test/acceptance/tests/lms/test_lms_courseware.py b/common/test/acceptance/tests/lms/test_lms_courseware.py
index a222c7ee46..33dd35f9bd 100644
--- a/common/test/acceptance/tests/lms/test_lms_courseware.py
+++ b/common/test/acceptance/tests/lms/test_lms_courseware.py
@@ -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
):
diff --git a/lms/djangoapps/courseware/tests/test_views.py b/lms/djangoapps/courseware/tests/test_views.py
index 016a98c5e6..eba5913f7b 100644
--- a/lms/djangoapps/courseware/tests/test_views.py
+++ b/lms/djangoapps/courseware/tests/test_views.py
@@ -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 = "'+Stark/Industries+'
"
+ 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/">Sequential1
'
+ .format(course_id.decode("utf-8")),
+ view
+ )
+
+ self.assertIn(
+ u'href="/courses/{}/courseware/Chapter_1/Sequential_2/">Sequential2'
+ .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()
diff --git a/lms/envs/common.py b/lms/envs/common.py
index 3daec93028..3a020983bf 100644
--- a/lms/envs/common.py
+++ b/lms/envs/common.py
@@ -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',
diff --git a/lms/static/js/courseware/accordion_events.js b/lms/static/js/courseware/accordion_events.js
new file mode 100644
index 0000000000..98c68cc5d6
--- /dev/null
+++ b/lms/static/js/courseware/accordion_events.js
@@ -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);
diff --git a/lms/templates/courseware/accordion.html b/lms/templates/courseware/accordion.html
index 921fee4e4d..0f78cb0365 100644
--- a/lms/templates/courseware/accordion.html
+++ b/lms/templates/courseware/accordion.html
@@ -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: