feat: emit signal for thread, response, and comment created events (#33395)
This commit is contained in:
@@ -16,6 +16,7 @@ from django.urls import reverse
|
||||
from eventtracking.processors.exceptions import EventEmissionExit
|
||||
from mock import ANY, Mock, patch
|
||||
from opaque_keys.edx.keys import CourseKey
|
||||
from openedx_events.learning.signals import FORUM_THREAD_CREATED, FORUM_THREAD_RESPONSE_CREATED, FORUM_RESPONSE_COMMENT_CREATED
|
||||
|
||||
from common.djangoapps.course_modes.models import CourseMode
|
||||
from common.djangoapps.course_modes.tests.factories import CourseModeFactory
|
||||
@@ -406,7 +407,7 @@ class ViewsQueryCountTestCase(
|
||||
return inner
|
||||
|
||||
@ddt.data(
|
||||
(ModuleStoreEnum.Type.split, 3, 8, 42),
|
||||
(ModuleStoreEnum.Type.split, 3, 8, 43),
|
||||
)
|
||||
@ddt.unpack
|
||||
@count_queries
|
||||
@@ -1735,6 +1736,8 @@ class ForumEventTestCase(ForumsEnableMixin, SharedModuleStoreTestCase, MockReque
|
||||
"""
|
||||
Check to make sure an event is fired when a user responds to a thread.
|
||||
"""
|
||||
event_receiver = Mock()
|
||||
FORUM_THREAD_RESPONSE_CREATED.connect(event_receiver)
|
||||
self._set_mock_request_data(mock_request, {
|
||||
"closed": False,
|
||||
"commentable_id": 'test_commentable_id',
|
||||
@@ -1754,12 +1757,29 @@ class ForumEventTestCase(ForumsEnableMixin, SharedModuleStoreTestCase, MockReque
|
||||
assert event['discussion']['id'] == 'test_thread_id'
|
||||
assert event['options']['followed'] is True
|
||||
|
||||
event_receiver.assert_called_once()
|
||||
|
||||
self.assertDictContainsSubset(
|
||||
{
|
||||
"signal": FORUM_THREAD_RESPONSE_CREATED,
|
||||
"sender": None,
|
||||
},
|
||||
event_receiver.call_args.kwargs
|
||||
)
|
||||
|
||||
self.assertIn(
|
||||
"thread",
|
||||
event_receiver.call_args.kwargs
|
||||
)
|
||||
|
||||
@patch('eventtracking.tracker.emit')
|
||||
@patch('openedx.core.djangoapps.django_comment_common.comment_client.utils.requests.request', autospec=True)
|
||||
def test_comment_event(self, mock_request, mock_emit):
|
||||
"""
|
||||
Ensure an event is fired when someone comments on a response.
|
||||
"""
|
||||
event_receiver = Mock()
|
||||
FORUM_RESPONSE_COMMENT_CREATED.connect(event_receiver)
|
||||
self._set_mock_request_data(mock_request, {
|
||||
"closed": False,
|
||||
"depth": 1,
|
||||
@@ -1781,6 +1801,19 @@ class ForumEventTestCase(ForumsEnableMixin, SharedModuleStoreTestCase, MockReque
|
||||
assert event['user_course_roles'] == ['Wizard']
|
||||
assert event['options']['followed'] is False
|
||||
|
||||
self.assertDictContainsSubset(
|
||||
{
|
||||
"signal": FORUM_RESPONSE_COMMENT_CREATED,
|
||||
"sender": None,
|
||||
},
|
||||
event_receiver.call_args.kwargs
|
||||
)
|
||||
|
||||
self.assertIn(
|
||||
"thread",
|
||||
event_receiver.call_args.kwargs
|
||||
)
|
||||
|
||||
@patch('eventtracking.tracker.emit')
|
||||
@patch('openedx.core.djangoapps.django_comment_common.comment_client.utils.requests.request', autospec=True)
|
||||
@ddt.data((
|
||||
@@ -1809,6 +1842,10 @@ class ForumEventTestCase(ForumsEnableMixin, SharedModuleStoreTestCase, MockReque
|
||||
team = CourseTeamFactory.create(discussion_topic_id=TEAM_COMMENTABLE_ID)
|
||||
CourseTeamMembershipFactory.create(team=team, user=user)
|
||||
|
||||
event_receiver = Mock()
|
||||
forum_event = views.TRACKING_LOG_TO_EVENT_MAPS.get(event_name)
|
||||
forum_event.connect(event_receiver)
|
||||
|
||||
self._set_mock_request_data(mock_request, {
|
||||
'closed': False,
|
||||
'commentable_id': TEAM_COMMENTABLE_ID,
|
||||
@@ -1825,6 +1862,19 @@ class ForumEventTestCase(ForumsEnableMixin, SharedModuleStoreTestCase, MockReque
|
||||
assert name == event_name
|
||||
assert event['team_id'] == team.team_id
|
||||
|
||||
self.assertDictContainsSubset(
|
||||
{
|
||||
"signal": forum_event,
|
||||
"sender": None,
|
||||
},
|
||||
event_receiver.call_args.kwargs
|
||||
)
|
||||
|
||||
self.assertIn(
|
||||
"thread",
|
||||
event_receiver.call_args.kwargs
|
||||
)
|
||||
|
||||
@ddt.data(
|
||||
('vote_for_thread', 'thread_id', 'thread'),
|
||||
('undo_vote_for_thread', 'thread_id', 'thread'),
|
||||
@@ -1863,6 +1913,10 @@ class ForumEventTestCase(ForumsEnableMixin, SharedModuleStoreTestCase, MockReque
|
||||
@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):
|
||||
event_receiver = Mock()
|
||||
for signal in views.TRACKING_LOG_TO_EVENT_MAPS.values():
|
||||
signal.connect(event_receiver)
|
||||
|
||||
self._set_mock_request_data(mock_request, {
|
||||
'closed': False,
|
||||
'commentable_id': 'test_commentable_id',
|
||||
@@ -1887,6 +1941,11 @@ class ForumEventTestCase(ForumsEnableMixin, SharedModuleStoreTestCase, MockReque
|
||||
assert event_data['user_forums_roles'] == ['Student']
|
||||
assert event_data['user_course_roles'] == ['Wizard']
|
||||
|
||||
# In case of events that doesn't have a correspondig Open edX events signal
|
||||
# we need to check that none of the openedx signals is called.
|
||||
# This is tested for all the events that are not tested above.
|
||||
event_receiver.assert_not_called()
|
||||
|
||||
|
||||
class UsersEndpointTestCase(ForumsEnableMixin, SharedModuleStoreTestCase, MockRequestSetupMixin):
|
||||
|
||||
|
||||
@@ -16,12 +16,18 @@ from django.views.decorators.clickjacking import xframe_options_exempt
|
||||
from django.views.decorators.http import require_GET, require_POST
|
||||
from eventtracking import tracker
|
||||
from opaque_keys.edx.keys import CourseKey
|
||||
from openedx_events.learning.data import DiscussionThreadData, UserData, UserPersonalData
|
||||
from openedx_events.learning.signals import (
|
||||
FORUM_RESPONSE_COMMENT_CREATED,
|
||||
FORUM_THREAD_CREATED,
|
||||
FORUM_THREAD_RESPONSE_CREATED
|
||||
)
|
||||
|
||||
import lms.djangoapps.discussion.django_comment_client.settings as cc_settings
|
||||
import openedx.core.djangoapps.django_comment_common.comment_client as cc
|
||||
from common.djangoapps.student.roles import GlobalStaff
|
||||
from common.djangoapps.util.file import store_uploaded_file
|
||||
from common.djangoapps.track import contexts
|
||||
from common.djangoapps.util.file import store_uploaded_file
|
||||
from lms.djangoapps.courseware.access import has_access
|
||||
from lms.djangoapps.courseware.courses import get_course_overview_with_access, get_course_with_access
|
||||
from lms.djangoapps.courseware.exceptions import CourseAccessRedirect
|
||||
@@ -42,7 +48,7 @@ from lms.djangoapps.discussion.django_comment_client.utils import (
|
||||
get_user_group_ids,
|
||||
is_comment_too_deep,
|
||||
prepare_content,
|
||||
sanitize_body,
|
||||
sanitize_body
|
||||
)
|
||||
from openedx.core.djangoapps.django_comment_common.signals import (
|
||||
comment_created,
|
||||
@@ -66,6 +72,12 @@ TRACKING_MAX_FORUM_BODY = 2000
|
||||
TRACKING_MAX_FORUM_TITLE = 1000
|
||||
_EVENT_NAME_TEMPLATE = 'edx.forum.{obj_type}.{action_name}'
|
||||
|
||||
TRACKING_LOG_TO_EVENT_MAPS = {
|
||||
'edx.forum.thread.created': FORUM_THREAD_CREATED,
|
||||
'edx.forum.response.created': FORUM_THREAD_RESPONSE_CREATED,
|
||||
'edx.forum.comment.created': FORUM_RESPONSE_COMMENT_CREATED,
|
||||
}
|
||||
|
||||
|
||||
def track_forum_event(request, event_name, course, obj, data, id_map=None):
|
||||
"""
|
||||
@@ -97,6 +109,41 @@ def track_forum_event(request, event_name, course, obj, data, id_map=None):
|
||||
with tracker.get_tracker().context(event_name, context):
|
||||
tracker.emit(event_name, data)
|
||||
|
||||
forum_event = TRACKING_LOG_TO_EVENT_MAPS.get(event_name, None)
|
||||
if forum_event is not None:
|
||||
forum_event.send_event(
|
||||
thread=DiscussionThreadData(
|
||||
anonymous=data.get('anonymous'),
|
||||
anonymous_to_peers=data.get('anonymous_to_peers'),
|
||||
body=data.get('body'),
|
||||
category_id=data.get('category_id'),
|
||||
category_name=data.get('category_name'),
|
||||
commentable_id=data.get('commentable_id'),
|
||||
group_id=data.get('group_id'),
|
||||
id=data.get('id'),
|
||||
team_id=data.get('team_id'),
|
||||
thread_type=data.get('thread_type'),
|
||||
title=data.get('title'),
|
||||
title_truncated=data.get('title_truncated'),
|
||||
truncated=data.get('truncated'),
|
||||
url=data.get('url'),
|
||||
discussion=data.get('discussion'),
|
||||
user_course_roles=data.get('user_course_roles'),
|
||||
user_forums_roles=data.get('user_forums_roles'),
|
||||
user=UserData(
|
||||
pii=UserPersonalData(
|
||||
username=user.username,
|
||||
email=user.email,
|
||||
name=user.profile.name,
|
||||
),
|
||||
id=user.id,
|
||||
is_active=user.is_active,
|
||||
),
|
||||
course_id=str(course.id),
|
||||
options=data.get('options'),
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def track_created_event(request, event_name, course, obj, data):
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user