diff --git a/lms/djangoapps/teams/models.py b/lms/djangoapps/teams/models.py index accedf6b56..cbcb822554 100644 --- a/lms/djangoapps/teams/models.py +++ b/lms/djangoapps/teams/models.py @@ -28,6 +28,7 @@ from xmodule_django.models import CourseKeyField from util.model_utils import slugify from student.models import LanguageField, CourseEnrollment from .errors import AlreadyOnTeamInCourse, NotEnrolledInCourseForTeam, ImmutableMembershipFieldException +from teams.utils import emit_team_event from teams import TEAM_DISCUSSION_CONTEXT @@ -247,3 +248,6 @@ class CourseTeamMembership(models.Model): membership.team.last_activity_at = now membership.team.save() membership.save() + emit_team_event('edx.team.activity_updated', membership.team.course_id, { + 'team_id': membership.team_id, + }) diff --git a/lms/djangoapps/teams/tests/test_models.py b/lms/djangoapps/teams/tests/test_models.py index ba9fc6f53c..753665a473 100644 --- a/lms/djangoapps/teams/tests/test_models.py +++ b/lms/djangoapps/teams/tests/test_models.py @@ -24,8 +24,9 @@ from opaque_keys.edx.keys import CourseKey from student.tests.factories import CourseEnrollmentFactory, UserFactory from .factories import CourseTeamFactory, CourseTeamMembershipFactory -from ..models import CourseTeam, CourseTeamMembership +from teams.models import CourseTeam, CourseTeamMembership from teams import TEAM_DISCUSSION_CONTEXT +from util.testing import EventTestMixin COURSE_KEY1 = CourseKey.from_string('edx/history/1') COURSE_KEY2 = CourseKey.from_string('edx/history/2') @@ -114,7 +115,7 @@ class TeamMembershipTest(SharedModuleStoreTestCase): @ddt.ddt -class TeamSignalsTest(SharedModuleStoreTestCase): +class TeamSignalsTest(EventTestMixin, SharedModuleStoreTestCase): """Tests for handling of team-related signals.""" SIGNALS_LIST = ( @@ -133,7 +134,7 @@ class TeamSignalsTest(SharedModuleStoreTestCase): def setUp(self): """Create a user with a team to test signals.""" - super(TeamSignalsTest, self).setUp() + super(TeamSignalsTest, self).setUp('teams.utils.tracker') self.user = UserFactory.create(username="user") self.moderator = UserFactory.create(username="moderator") self.team = CourseTeamFactory(discussion_topic_id=self.DISCUSSION_TOPIC_ID) @@ -168,9 +169,14 @@ class TeamSignalsTest(SharedModuleStoreTestCase): now = datetime.utcnow().replace(tzinfo=pytz.utc) self.assertGreater(now, team.last_activity_at) self.assertGreater(now, team_membership.last_activity_at) + self.assert_event_emitted( + 'edx.team.activity_updated', + team_id=team.id, + ) else: self.assertEqual(team.last_activity_at, team_last_activity) self.assertEqual(team_membership.last_activity_at, team_membership_last_activity) + self.assert_no_events_were_emitted() @ddt.data( *itertools.product( diff --git a/lms/djangoapps/teams/tests/test_views.py b/lms/djangoapps/teams/tests/test_views.py index f1610a6d99..cc7fcc23ed 100644 --- a/lms/djangoapps/teams/tests/test_views.py +++ b/lms/djangoapps/teams/tests/test_views.py @@ -418,7 +418,7 @@ class TestListTeamsAPI(EventTestMixin, TeamAPITestCase): """Test cases for the team listing API endpoint.""" def setUp(self): # pylint: disable=arguments-differ - super(TestListTeamsAPI, self).setUp('teams.views.tracker') + super(TestListTeamsAPI, self).setUp('teams.utils.tracker') @ddt.data( (None, 401), @@ -592,7 +592,7 @@ class TestCreateTeamAPI(EventTestMixin, TeamAPITestCase): """Test cases for the team creation endpoint.""" def setUp(self): # pylint: disable=arguments-differ - super(TestCreateTeamAPI, self).setUp('teams.views.tracker') + super(TestCreateTeamAPI, self).setUp('teams.utils.tracker') @ddt.data( (None, 401), @@ -803,7 +803,7 @@ class TestDeleteTeamAPI(EventTestMixin, TeamAPITestCase): """Test cases for the team delete endpoint.""" def setUp(self): # pylint: disable=arguments-differ - super(TestDeleteTeamAPI, self).setUp('teams.views.tracker') + super(TestDeleteTeamAPI, self).setUp('teams.utils.tracker') @ddt.data( (None, 401), @@ -853,7 +853,7 @@ class TestUpdateTeamAPI(EventTestMixin, TeamAPITestCase): """Test cases for the team update endpoint.""" def setUp(self): # pylint: disable=arguments-differ - super(TestUpdateTeamAPI, self).setUp('teams.views.tracker') + super(TestUpdateTeamAPI, self).setUp('teams.utils.tracker') @ddt.data( (None, 401), @@ -1182,7 +1182,7 @@ class TestCreateMembershipAPI(EventTestMixin, TeamAPITestCase): """Test cases for the membership creation endpoint.""" def setUp(self): # pylint: disable=arguments-differ - super(TestCreateMembershipAPI, self).setUp('teams.views.tracker') + super(TestCreateMembershipAPI, self).setUp('teams.utils.tracker') @ddt.data( (None, 401), @@ -1346,7 +1346,7 @@ class TestDeleteMembershipAPI(EventTestMixin, TeamAPITestCase): """Test cases for the membership deletion endpoint.""" def setUp(self): # pylint: disable=arguments-differ - super(TestDeleteMembershipAPI, self).setUp('teams.views.tracker') + super(TestDeleteMembershipAPI, self).setUp('teams.utils.tracker') @ddt.data( (None, 401), diff --git a/lms/djangoapps/teams/utils.py b/lms/djangoapps/teams/utils.py new file mode 100644 index 0000000000..dc576397b5 --- /dev/null +++ b/lms/djangoapps/teams/utils.py @@ -0,0 +1,14 @@ +"""Utility methods related to teams.""" + +from eventtracking import tracker +from track import contexts + + +def emit_team_event(event_name, course_key, event_data): + """ + Emit team events with the correct course id context. + """ + context = contexts.course_context_from_course_id(course_key) + + with tracker.get_tracker().context(event_name, context): + tracker.emit(event_name, event_data) diff --git a/lms/djangoapps/teams/views.py b/lms/djangoapps/teams/views.py index 07f477fb6c..6a6af4e5d9 100644 --- a/lms/djangoapps/teams/views.py +++ b/lms/djangoapps/teams/views.py @@ -39,8 +39,6 @@ from opaque_keys import InvalidKeyError from opaque_keys.edx.keys import CourseKey from courseware.courses import get_course_with_access, has_access -from eventtracking import tracker -from track import contexts from student.models import CourseEnrollment, CourseAccessRole from student.roles import CourseStaffRole from django_comment_client.utils import has_discussion_privileges @@ -59,6 +57,7 @@ from .serializers import ( ) from .search_indexes import CourseTeamIndexer from .errors import AlreadyOnTeamInCourse, ElasticSearchConnectionError, NotEnrolledInCourseForTeam +from .utils import emit_team_event TEAM_MEMBERSHIPS_PER_PAGE = 2 TOPICS_PER_PAGE = 12 @@ -67,16 +66,6 @@ MAXIMUM_SEARCH_SIZE = 100000 log = logging.getLogger(__name__) -def emit_team_event(event_name, course_key, event_data): - """ - Emit team events with the correct course id context. - """ - context = contexts.course_context_from_course_id(course_key) - - with tracker.get_tracker().context(event_name, context): - tracker.emit(event_name, event_data) - - @receiver(post_save, sender=CourseTeam) def team_post_save_callback(sender, instance, **kwargs): # pylint: disable=unused-argument """ Emits signal after the team is saved. """