Skip to content

Commit

Permalink
feat: emit signal for thread, response, and comment created events (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
Ian2012 authored Oct 30, 2023
1 parent 99b6f6b commit 9e65024
Show file tree
Hide file tree
Showing 2 changed files with 109 additions and 3 deletions.
61 changes: 60 additions & 1 deletion lms/djangoapps/discussion/django_comment_client/base/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
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
Expand Down Expand Up @@ -406,7 +407,7 @@ def inner(self, default_store, block_count, mongo_calls, sql_queries, *args, **k
return inner

@ddt.data(
(ModuleStoreEnum.Type.split, 3, 8, 42),
(ModuleStoreEnum.Type.split, 3, 8, 43),
)
@ddt.unpack
@count_queries
Expand Down Expand Up @@ -1735,6 +1736,8 @@ def test_response_event(self, mock_request, mock_emit):
"""
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',
Expand All @@ -1754,12 +1757,29 @@ def test_response_event(self, mock_request, mock_emit):
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,
Expand All @@ -1781,6 +1801,19 @@ def test_comment_event(self, mock_request, mock_emit):
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((
Expand Down Expand Up @@ -1809,6 +1842,10 @@ def test_team_events(self, view_name, event_name, view_data, view_kwargs, mock_r
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,
Expand All @@ -1825,6 +1862,19 @@ def test_team_events(self, view_name, event_name, view_data, view_kwargs, mock_r
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'),
Expand Down Expand Up @@ -1863,6 +1913,10 @@ def test_thread_voted_event(self, view_name, obj_id_name, obj_type, mock_request
@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',
Expand All @@ -1887,6 +1941,11 @@ def test_thread_followed_event(self, view_name, mock_request, mock_emit):
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):

Expand Down
51 changes: 49 additions & 2 deletions lms/djangoapps/discussion/django_comment_client/base/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,18 @@
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
Expand All @@ -42,7 +48,7 @@
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,
Expand All @@ -66,6 +72,12 @@
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):
"""
Expand Down Expand Up @@ -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):
"""
Expand Down

0 comments on commit 9e65024

Please sign in to comment.