Merge pull request #9607 from edx/diana/teams-event-tracking

Add teams eventing and tests.
This commit is contained in:
Diana Huang
2015-09-04 11:32:25 -04:00
3 changed files with 137 additions and 10 deletions

View File

@@ -14,6 +14,7 @@ from rest_framework.test import APITestCase, APIClient
from courseware.tests.factories import StaffFactory
from common.test.utils import skip_signal
from util.testing import EventTestMixin
from student.tests.factories import UserFactory, AdminFactory, CourseEnrollmentFactory
from student.models import CourseEnrollment
from xmodule.modulestore.tests.django_utils import SharedModuleStoreTestCase
@@ -529,9 +530,12 @@ class TestListTeamsAPI(TeamAPITestCase):
@ddt.ddt
class TestCreateTeamAPI(TeamAPITestCase):
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')
@ddt.data(
(None, 401),
('student_inactive', 401),
@@ -549,11 +553,15 @@ class TestCreateTeamAPI(TeamAPITestCase):
teams = self.get_teams_list(user=user)
self.assertIn("New Team", [team['name'] for team in teams['results']])
def _expected_team_id(self, team, expected_prefix):
""" Return the team id that we'd expect given this team data and this prefix. """
return expected_prefix + '-' + team['discussion_topic_id']
def verify_expected_team_id(self, team, expected_prefix):
""" Verifies that the team id starts with the specified prefix and ends with the discussion_topic_id """
self.assertIn('id', team)
self.assertIn('discussion_topic_id', team)
self.assertEqual(team['id'], expected_prefix + '-' + team['discussion_topic_id'])
self.assertEqual(team['id'], self._expected_team_id(team, expected_prefix))
def test_naming(self):
new_teams = [
@@ -640,6 +648,19 @@ class TestCreateTeamAPI(TeamAPITestCase):
self.verify_expected_team_id(team, 'fully-specified-team')
del team['id']
self.assert_event_emitted(
'edx.team.created',
team_id=self._expected_team_id(team, 'fully-specified-team'),
course_id=unicode(self.test_course_1.id),
)
self.assert_event_emitted(
'edx.team.learner_added',
team_id=self._expected_team_id(team, 'fully-specified-team'),
course_id=unicode(self.test_course_1.id),
user_id=self.users[creator].id,
add_method='added_on_create'
)
# Remove date_created and discussion_topic_id because they change between test runs
del team['date_created']
del team['discussion_topic_id']
@@ -1026,9 +1047,12 @@ class TestListMembershipAPI(TeamAPITestCase):
@ddt.ddt
class TestCreateMembershipAPI(TeamAPITestCase):
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')
@ddt.data(
(None, 401),
('student_inactive', 401),
@@ -1053,6 +1077,18 @@ class TestCreateMembershipAPI(TeamAPITestCase):
memberships = self.get_membership_list(200, {'team_id': self.solar_team.team_id})
self.assertEqual(memberships['count'], 2)
add_method = 'joined_from_team_view' if user == 'student_enrolled_not_on_team' else 'added_by_another_user'
self.assert_event_emitted(
'edx.team.learner_added',
team_id=self.solar_team.team_id,
user_id=self.users['student_enrolled_not_on_team'].id,
course_id=unicode(self.solar_team.course_id),
add_method=add_method
)
else:
self.assert_no_events_were_emitted()
def test_no_username(self):
response = self.post_create_membership(400, {'team_id': self.solar_team.team_id})
self.assertIn('username', json.loads(response.content)['field_errors'])
@@ -1176,9 +1212,12 @@ class TestDetailMembershipAPI(TeamAPITestCase):
@ddt.ddt
class TestDeleteMembershipAPI(TeamAPITestCase):
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')
@ddt.data(
(None, 401),
('student_inactive', 401),
@@ -1198,6 +1237,18 @@ class TestDeleteMembershipAPI(TeamAPITestCase):
user=user
)
if status == 204:
remove_method = 'self_removal' if user == 'student_enrolled' else 'removed_by_admin'
self.assert_event_emitted(
'edx.team.learner_removed',
team_id=self.solar_team.team_id,
course_id=unicode(self.solar_team.course_id),
user_id=self.users['student_enrolled'].id,
remove_method=remove_method
)
else:
self.assert_no_events_were_emitted()
def test_bad_team(self):
self.delete_membership('no_such_team', self.users['student_enrolled'].username, 404)

View File

@@ -34,6 +34,7 @@ from xmodule.modulestore.django import modulestore
from opaque_keys import InvalidKeyError
from opaque_keys.edx.keys import CourseKey
from eventtracking import tracker
from courseware.courses import get_course_with_access, has_access
from student.models import CourseEnrollment, CourseAccessRole
from student.roles import CourseStaffRole
@@ -417,9 +418,22 @@ class TeamsListView(ExpandableFieldViewMixin, GenericAPIView):
}, status=status.HTTP_400_BAD_REQUEST)
else:
team = serializer.save()
tracker.emit('edx.team.created', {
'team_id': team.team_id,
'course_id': unicode(course_id)
})
if not team_administrator:
# Add the creating user to the team.
team.add_user(request.user)
tracker.emit(
'edx.team.learner_added',
{
'team_id': team.team_id,
'user_id': request.user.id,
'course_id': unicode(team.course_id),
'add_method': 'added_on_create'
}
)
return Response(CourseTeamSerializer(team).data)
def get_page(self):
@@ -974,6 +988,15 @@ class MembershipListView(ExpandableFieldViewMixin, GenericAPIView):
try:
membership = team.add_user(user)
tracker.emit(
'edx.team.learner_added',
{
'team_id': team.team_id,
'user_id': user.id,
'course_id': unicode(team.course_id),
'add_method': 'joined_from_team_view' if user == request.user else 'added_by_another_user'
}
)
except AlreadyOnTeamInCourse:
return Response(
build_api_error(
@@ -1100,6 +1123,15 @@ class MembershipDetailView(ExpandableFieldViewMixin, GenericAPIView):
if has_team_api_access(request.user, team.course_id, access_username=username):
membership = self.get_membership(username, team)
membership.delete()
tracker.emit(
'edx.team.learner_removed',
{
'team_id': team.team_id,
'course_id': unicode(team.course_id),
'user_id': membership.user.id,
'remove_method': 'self_removal' if membership.user == request.user else 'removed_by_admin'
}
)
return Response(status=status.HTTP_204_NO_CONTENT)
else:
return Response(status=status.HTTP_404_NOT_FOUND)