Commit ef563e42 by Sven Marnach

Add tests for the discussion forum vote events.

parent cf5d276a
...@@ -1641,6 +1641,40 @@ class ForumEventTestCase(ModuleStoreTestCase, MockRequestSetupMixin): ...@@ -1641,6 +1641,40 @@ class ForumEventTestCase(ModuleStoreTestCase, MockRequestSetupMixin):
self.assertEqual(name, event_name) self.assertEqual(name, event_name)
self.assertEqual(event['team_id'], team.team_id) self.assertEqual(event['team_id'], team.team_id)
@ddt.data(
('vote_for_thread', 'thread_id', 'thread'),
('undo_vote_for_thread', 'thread_id', 'thread'),
('vote_for_comment', 'comment_id', 'response'),
('undo_vote_for_comment', 'comment_id', 'response'),
)
@ddt.unpack
@patch('eventtracking.tracker.emit')
@patch('lms.lib.comment_client.utils.requests.request')
def test_thread_voted_event(self, view_name, obj_id_name, obj_type, mock_request, mock_emit):
undo = view_name.startswith('undo')
self._set_mock_request_data(mock_request, {
'closed': False,
'commentable_id': 'test_commentable_id',
'username': 'gumprecht',
})
request = RequestFactory().post('dummy_url', {})
request.user = self.student
request.view_name = view_name
view_function = getattr(views, view_name)
kwargs = dict(course_id=unicode(self.course.id))
kwargs[obj_id_name] = obj_id_name
if not undo:
kwargs.update(value='up')
view_function(request, **kwargs)
self.assertTrue(mock_emit.called)
event_name, event = mock_emit.call_args[0]
self.assertEqual(event_name, 'edx.forum.{}.voted'.format(obj_type))
self.assertEqual(event['target_username'], 'gumprecht')
self.assertEqual(event['undo_vote'], undo)
self.assertEqual(event['vote_value'], 'up')
class UsersEndpointTestCase(ModuleStoreTestCase, MockRequestSetupMixin): class UsersEndpointTestCase(ModuleStoreTestCase, MockRequestSetupMixin):
......
...@@ -82,6 +82,9 @@ def track_forum_event(request, event_name, course, obj, data, id_map=None): ...@@ -82,6 +82,9 @@ def track_forum_event(request, event_name, course, obj, data, id_map=None):
def track_created_event(request, event_name, course, obj, data): def track_created_event(request, event_name, course, obj, data):
"""
Send analytics event for a newly created thread, response or comment.
"""
if len(obj.body) > TRACKING_MAX_FORUM_BODY: if len(obj.body) > TRACKING_MAX_FORUM_BODY:
data['truncated'] = True data['truncated'] = True
else: else:
...@@ -91,6 +94,9 @@ def track_created_event(request, event_name, course, obj, data): ...@@ -91,6 +94,9 @@ def track_created_event(request, event_name, course, obj, data):
def track_thread_created_event(request, course, thread, followed): def track_thread_created_event(request, course, thread, followed):
"""
Send analytics event for a newly created thread.
"""
event_name = _EVENT_NAME_TEMPLATE.format(obj_type='thread', action_name='created') event_name = _EVENT_NAME_TEMPLATE.format(obj_type='thread', action_name='created')
event_data = { event_data = {
'commentable_id': thread.commentable_id, 'commentable_id': thread.commentable_id,
...@@ -109,6 +115,9 @@ def track_thread_created_event(request, course, thread, followed): ...@@ -109,6 +115,9 @@ def track_thread_created_event(request, course, thread, followed):
def track_comment_created_event(request, course, comment, commentable_id, followed): def track_comment_created_event(request, course, comment, commentable_id, followed):
"""
Send analytics event for a newly created response or comment.
"""
obj_type = 'comment' if comment.get("parent_id") else 'response' obj_type = 'comment' if comment.get("parent_id") else 'response'
event_name = _EVENT_NAME_TEMPLATE.format(obj_type=obj_type, action_name='created') event_name = _EVENT_NAME_TEMPLATE.format(obj_type=obj_type, action_name='created')
event_data = { event_data = {
...@@ -123,6 +132,9 @@ def track_comment_created_event(request, course, comment, commentable_id, follow ...@@ -123,6 +132,9 @@ def track_comment_created_event(request, course, comment, commentable_id, follow
def track_voted_event(request, course, obj, vote_value, undo_vote=False): def track_voted_event(request, course, obj, vote_value, undo_vote=False):
"""
Send analytics event for a vote on a thread or response.
"""
if isinstance(obj, cc.Thread): if isinstance(obj, cc.Thread):
obj_type = 'thread' obj_type = 'thread'
else: else:
...@@ -137,10 +149,19 @@ def track_voted_event(request, course, obj, vote_value, undo_vote=False): ...@@ -137,10 +149,19 @@ def track_voted_event(request, course, obj, vote_value, undo_vote=False):
track_forum_event(request, event_name, course, obj, event_data) track_forum_event(request, event_name, course, obj, event_data)
def permitted(fn): def permitted(func):
@functools.wraps(fn) """
View decorator to verify the user is authorized to access this endpoint.
"""
@functools.wraps(func)
def wrapper(request, *args, **kwargs): def wrapper(request, *args, **kwargs):
"""
Wrapper for the view that only calls the view if the user is authorized.
"""
def fetch_content(): def fetch_content():
"""
Extract the forum object from the keyword arguments to the view.
"""
if "thread_id" in kwargs: if "thread_id" in kwargs:
content = cc.Thread.find(kwargs["thread_id"]).to_dict() content = cc.Thread.find(kwargs["thread_id"]).to_dict()
elif "comment_id" in kwargs: elif "comment_id" in kwargs:
...@@ -152,13 +173,16 @@ def permitted(fn): ...@@ -152,13 +173,16 @@ def permitted(fn):
return content return content
course_key = SlashSeparatedCourseKey.from_deprecated_string(kwargs['course_id']) course_key = SlashSeparatedCourseKey.from_deprecated_string(kwargs['course_id'])
if check_permissions_by_view(request.user, course_key, fetch_content(), request.view_name): if check_permissions_by_view(request.user, course_key, fetch_content(), request.view_name):
return fn(request, *args, **kwargs) return func(request, *args, **kwargs)
else: else:
return JsonError("unauthorized", status=401) return JsonError("unauthorized", status=401)
return wrapper return wrapper
def ajax_content_response(request, course_key, content): def ajax_content_response(request, course_key, content):
"""
Standard AJAX response returning the content hierarchy of the current thread.
"""
user_info = cc.User.from_django_user(request.user).to_dict() user_info = cc.User.from_django_user(request.user).to_dict()
annotated_content_info = get_annotated_content_info(course_key, content, request.user, user_info) annotated_content_info = get_annotated_content_info(course_key, content, request.user, user_info)
return JsonResponse({ return JsonResponse({
...@@ -479,7 +503,7 @@ def _vote_or_unvote(request, course_id, obj, value='up', undo_vote=False): ...@@ -479,7 +503,7 @@ def _vote_or_unvote(request, course_id, obj, value='up', undo_vote=False):
@permitted @permitted
def vote_for_comment(request, course_id, comment_id, value): def vote_for_comment(request, course_id, comment_id, value):
""" """
given a course_id and comment_id, Given a course_id and comment_id, vote for this response. AJAX only.
""" """
comment = cc.Comment.find(comment_id) comment = cc.Comment.find(comment_id)
result = _vote_or_unvote(request, course_id, comment, value) result = _vote_or_unvote(request, course_id, comment, value)
......
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