diff --git a/edx_exams/apps/core/api.py b/edx_exams/apps/core/api.py index 2b1fcdfa..0b13c08b 100644 --- a/edx_exams/apps/core/api.py +++ b/edx_exams/apps/core/api.py @@ -9,6 +9,11 @@ from django.utils import dateparse, timezone from opaque_keys.edx.keys import CourseKey, UsageKey +# TODO: Change the signal to the appropriate signal type. +from openedx_events.learning.signals import STUDENT_REGISTRATION_COMPLETED +from openedx_events.learning.data import UserData, UserPersonalData + + from edx_exams.apps.core.exam_types import OnboardingExamType, PracticeExamType, get_exam_type from edx_exams.apps.core.exceptions import ( ExamAttemptAlreadyExists, @@ -96,6 +101,11 @@ def update_attempt_status(attempt_id, to_status): if to_status == ExamAttemptStatus.submitted: attempt_obj.end_time = datetime.now(pytz.UTC) + _emit_TODO_NAME_event( + attempt_obj.user.username, + attempt_obj.exam.content_id + ) + attempt_obj.status = to_status attempt_obj.save() @@ -161,6 +171,25 @@ def _calculate_allowed_mins(exam): return allowed_time_limit_mins +def _emit_TODO_NAME_event(username, content_id): # pylint: disable=unused-argument + # .. event_implemented_name: TODO + STUDENT_REGISTRATION_COMPLETED.send_event( + user=UserData( + id=1, + is_active=True, + pii=UserPersonalData( + username=username, + email='test', + name='test', + ) + # data=InstructorCompletionData( + # username=username, + # content_id=content_id, + # ) + ) + ) + + def get_exam_attempt_time_remaining(exam_attempt, now=None): """ For timed exam attempt, get the time remaining in seconds. diff --git a/edx_exams/apps/core/tests/test_api.py b/edx_exams/apps/core/tests/test_api.py index 69d5155e..ebee3090 100644 --- a/edx_exams/apps/core/tests/test_api.py +++ b/edx_exams/apps/core/tests/test_api.py @@ -11,6 +11,7 @@ from django.utils import timezone from freezegun import freeze_time from opaque_keys.edx.keys import CourseKey, UsageKey +from openedx_events.learning.data import UserData, UserPersonalData from edx_exams.apps.api.test_utils import ExamsAPITestCase from edx_exams.apps.core.api import ( @@ -298,6 +299,25 @@ def test_submit_attempt(self): self.assertEqual(updated_attempt.status, ExamAttemptStatus.submitted) self.assertEqual(updated_attempt.end_time, timezone.now()) + @patch('edx_exams.apps.core.api.STUDENT_REGISTRATION_COMPLETED.send_event') + def test_submit_attempt_event_emitted(self, mock_event_send): + """ + Test that when an exam is submitted, the appropriate Open edX event is emitted. + """ + update_attempt_status(self.exam_attempt.id, ExamAttemptStatus.submitted) + self.assertEqual(mock_event_send.call_count, 1) + + expected_data = UserData( + id=1, + is_active=True, + pii=UserPersonalData( + username=self.user.username, + email='test', + name='test', + ) + ) + mock_event_send.assert_called_with(user=expected_data) + def test_illegal_start(self): """ Test that an already started exam cannot be started