feat: emit signal for thread, response, and comment created events (#33395)

This commit is contained in:
Cristhian Garcia
2023-10-30 10:46:39 -05:00
committed by GitHub
parent 99b6f6b6e9
commit 9e65024744
2 changed files with 109 additions and 3 deletions

View File

@@ -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):

View File

@@ -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):
"""