feat: add tracking event for following post
This commit is contained in:
@@ -1859,6 +1859,34 @@ class ForumEventTestCase(ForumsEnableMixin, SharedModuleStoreTestCase, MockReque
|
|||||||
assert event['undo_vote'] == undo
|
assert event['undo_vote'] == undo
|
||||||
assert event['vote_value'] == 'up'
|
assert event['vote_value'] == 'up'
|
||||||
|
|
||||||
|
@ddt.data('follow_thread', 'unfollow_thread',)
|
||||||
|
@patch('eventtracking.tracker.emit')
|
||||||
|
@patch('openedx.core.djangoapps.django_comment_common.comment_client.utils.requests.request', autospec=True)
|
||||||
|
def test_thread_followed_event(self, view_name, mock_request, mock_emit):
|
||||||
|
self._set_mock_request_data(mock_request, {
|
||||||
|
'closed': False,
|
||||||
|
'commentable_id': 'test_commentable_id',
|
||||||
|
'username': 'test_user',
|
||||||
|
})
|
||||||
|
request = RequestFactory().post('dummy_url', {})
|
||||||
|
request.user = self.student
|
||||||
|
request.view_name = view_name
|
||||||
|
view_function = getattr(views, view_name)
|
||||||
|
kwargs = dict(course_id=str(self.course.id))
|
||||||
|
kwargs['thread_id'] = 'thread_id'
|
||||||
|
view_function(request, **kwargs)
|
||||||
|
|
||||||
|
assert mock_emit.called
|
||||||
|
event_name, event_data = mock_emit.call_args[0]
|
||||||
|
action_name = 'followed' if view_name == 'follow_thread' else 'unfollowed'
|
||||||
|
expected_action_value = True if view_name == 'follow_thread' else False
|
||||||
|
assert event_name == f'edx.forum.thread.{action_name}'
|
||||||
|
assert event_data['commentable_id'] == 'test_commentable_id'
|
||||||
|
assert event_data['id'] == 'thread_id'
|
||||||
|
assert event_data['followed'] == expected_action_value
|
||||||
|
assert event_data['user_forums_roles'] == ['Student']
|
||||||
|
assert event_data['user_course_roles'] == ['Wizard']
|
||||||
|
|
||||||
|
|
||||||
class UsersEndpointTestCase(ForumsEnableMixin, SharedModuleStoreTestCase, MockRequestSetupMixin):
|
class UsersEndpointTestCase(ForumsEnableMixin, SharedModuleStoreTestCase, MockRequestSetupMixin):
|
||||||
|
|
||||||
|
|||||||
@@ -134,6 +134,20 @@ def track_thread_created_event(request, course, thread, followed, from_mfe_sideb
|
|||||||
track_created_event(request, event_name, course, thread, event_data)
|
track_created_event(request, event_name, course, thread, event_data)
|
||||||
|
|
||||||
|
|
||||||
|
def track_thread_followed_event(request, course, thread, followed):
|
||||||
|
"""
|
||||||
|
Send analytics event for a newly followed/unfollowed thread.
|
||||||
|
"""
|
||||||
|
action_name = 'followed' if followed else 'unfollowed'
|
||||||
|
event_name = _EVENT_NAME_TEMPLATE.format(obj_type='thread', action_name=action_name)
|
||||||
|
event_data = {
|
||||||
|
'commentable_id': thread.commentable_id,
|
||||||
|
'id': thread.id,
|
||||||
|
'followed': followed,
|
||||||
|
}
|
||||||
|
track_forum_event(request, event_name, course, thread, event_data)
|
||||||
|
|
||||||
|
|
||||||
def track_comment_created_event(request, course, comment, commentable_id, followed, from_mfe_sidebar=False):
|
def track_comment_created_event(request, course, comment, commentable_id, followed, from_mfe_sidebar=False):
|
||||||
"""
|
"""
|
||||||
Send analytics event for a newly created response or comment.
|
Send analytics event for a newly created response or comment.
|
||||||
@@ -938,9 +952,12 @@ def un_pin_thread(request, course_id, thread_id):
|
|||||||
@permitted
|
@permitted
|
||||||
def follow_thread(request, course_id, thread_id): # lint-amnesty, pylint: disable=missing-function-docstring, unused-argument
|
def follow_thread(request, course_id, thread_id): # lint-amnesty, pylint: disable=missing-function-docstring, unused-argument
|
||||||
user = cc.User.from_django_user(request.user)
|
user = cc.User.from_django_user(request.user)
|
||||||
|
course_key = CourseKey.from_string(course_id)
|
||||||
|
course = get_course_by_id(course_key)
|
||||||
thread = cc.Thread.find(thread_id)
|
thread = cc.Thread.find(thread_id)
|
||||||
user.follow(thread)
|
user.follow(thread)
|
||||||
thread_followed.send(sender=None, user=request.user, post=thread)
|
thread_followed.send(sender=None, user=request.user, post=thread)
|
||||||
|
track_thread_followed_event(request, course, thread, True)
|
||||||
return JsonResponse({})
|
return JsonResponse({})
|
||||||
|
|
||||||
|
|
||||||
@@ -966,10 +983,13 @@ def unfollow_thread(request, course_id, thread_id): # lint-amnesty, pylint: dis
|
|||||||
given a course id and thread id, stop following this thread
|
given a course id and thread id, stop following this thread
|
||||||
ajax only
|
ajax only
|
||||||
"""
|
"""
|
||||||
|
course_key = CourseKey.from_string(course_id)
|
||||||
|
course = get_course_by_id(course_key)
|
||||||
user = cc.User.from_django_user(request.user)
|
user = cc.User.from_django_user(request.user)
|
||||||
thread = cc.Thread.find(thread_id)
|
thread = cc.Thread.find(thread_id)
|
||||||
user.unfollow(thread)
|
user.unfollow(thread)
|
||||||
thread_unfollowed.send(sender=None, user=request.user, post=thread)
|
thread_unfollowed.send(sender=None, user=request.user, post=thread)
|
||||||
|
track_thread_followed_event(request, course, thread, False)
|
||||||
return JsonResponse({})
|
return JsonResponse({})
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -93,7 +93,7 @@ from ..django_comment_client.base.views import (
|
|||||||
track_voted_event,
|
track_voted_event,
|
||||||
track_discussion_reported_event,
|
track_discussion_reported_event,
|
||||||
track_discussion_unreported_event,
|
track_discussion_unreported_event,
|
||||||
track_forum_search_event
|
track_forum_search_event, track_thread_followed_event
|
||||||
)
|
)
|
||||||
from ..django_comment_client.utils import (
|
from ..django_comment_client.utils import (
|
||||||
get_group_id_for_user,
|
get_group_id_for_user,
|
||||||
@@ -1333,7 +1333,7 @@ def _do_extra_actions(api_content, cc_content, request_fields, actions_form, con
|
|||||||
if field in request_fields and field in api_content and form_value != api_content[field]:
|
if field in request_fields and field in api_content and form_value != api_content[field]:
|
||||||
api_content[field] = form_value
|
api_content[field] = form_value
|
||||||
if field == "following":
|
if field == "following":
|
||||||
_handle_following_field(form_value, context["cc_requester"], cc_content)
|
_handle_following_field(form_value, context["cc_requester"], cc_content, request)
|
||||||
elif field == "abuse_flagged":
|
elif field == "abuse_flagged":
|
||||||
_handle_abuse_flagged_field(form_value, context["cc_requester"], cc_content, request)
|
_handle_abuse_flagged_field(form_value, context["cc_requester"], cc_content, request)
|
||||||
elif field == "voted":
|
elif field == "voted":
|
||||||
@@ -1346,12 +1346,15 @@ def _do_extra_actions(api_content, cc_content, request_fields, actions_form, con
|
|||||||
raise ValidationError({field: ["Invalid Key"]})
|
raise ValidationError({field: ["Invalid Key"]})
|
||||||
|
|
||||||
|
|
||||||
def _handle_following_field(form_value, user, cc_content):
|
def _handle_following_field(form_value, user, cc_content, request):
|
||||||
"""follow/unfollow thread for the user"""
|
"""follow/unfollow thread for the user"""
|
||||||
|
course_key = CourseKey.from_string(cc_content.course_id)
|
||||||
|
course = get_course_with_access(request.user, 'load', course_key)
|
||||||
if form_value:
|
if form_value:
|
||||||
user.follow(cc_content)
|
user.follow(cc_content)
|
||||||
else:
|
else:
|
||||||
user.unfollow(cc_content)
|
user.unfollow(cc_content)
|
||||||
|
track_thread_followed_event(request, course, cc_content, form_value)
|
||||||
|
|
||||||
|
|
||||||
def _handle_abuse_flagged_field(form_value, user, cc_content, request):
|
def _handle_abuse_flagged_field(form_value, user, cc_content, request):
|
||||||
|
|||||||
@@ -2709,7 +2709,8 @@ class UpdateThreadTest(
|
|||||||
|
|
||||||
@ddt.data(*itertools.product([True, False], [True, False]))
|
@ddt.data(*itertools.product([True, False], [True, False]))
|
||||||
@ddt.unpack
|
@ddt.unpack
|
||||||
def test_following(self, old_following, new_following):
|
@mock.patch("eventtracking.tracker.emit")
|
||||||
|
def test_following(self, old_following, new_following, mock_emit):
|
||||||
"""
|
"""
|
||||||
Test attempts to edit the "following" field.
|
Test attempts to edit the "following" field.
|
||||||
|
|
||||||
@@ -2739,6 +2740,13 @@ class UpdateThreadTest(
|
|||||||
)
|
)
|
||||||
request_data.pop("request_id", None)
|
request_data.pop("request_id", None)
|
||||||
assert request_data == {'source_type': ['thread'], 'source_id': ['test_thread']}
|
assert request_data == {'source_type': ['thread'], 'source_id': ['test_thread']}
|
||||||
|
event_name, event_data = mock_emit.call_args[0]
|
||||||
|
expected_event_action = 'followed' if new_following else 'unfollowed'
|
||||||
|
assert event_name == f'edx.forum.thread.{expected_event_action}'
|
||||||
|
assert event_data['commentable_id'] == 'original_topic'
|
||||||
|
assert event_data['id'] == 'test_thread'
|
||||||
|
assert event_data['followed'] == new_following
|
||||||
|
assert event_data['user_forums_roles'] == ['Student']
|
||||||
|
|
||||||
@ddt.data(*itertools.product([True, False], [True, False]))
|
@ddt.data(*itertools.product([True, False], [True, False]))
|
||||||
@ddt.unpack
|
@ddt.unpack
|
||||||
|
|||||||
Reference in New Issue
Block a user