Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: emit verified event for attempt #186

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 12 additions & 3 deletions edx_exams/apps/core/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
ExamIllegalStatusTransition
)
from edx_exams.apps.core.models import Exam, ExamAttempt
from edx_exams.apps.core.signals.signals import emit_exam_attempt_submitted_event
from edx_exams.apps.core.signals.signals import emit_exam_attempt_submitted_event, emit_exam_attempt_verified_event
from edx_exams.apps.core.statuses import ExamAttemptStatus

log = logging.getLogger(__name__)
Expand Down Expand Up @@ -94,18 +94,27 @@ def update_attempt_status(attempt_id, to_status):
attempt_obj.start_time = datetime.now(pytz.UTC)
attempt_obj.allowed_time_limit_mins = _calculate_allowed_mins(attempt_obj.exam)

course_key = CourseKey.from_string(attempt_obj.exam.course_id)
usage_key = UsageKey.from_string(attempt_obj.exam.content_id)

if to_status == ExamAttemptStatus.submitted:
attempt_obj.end_time = datetime.now(pytz.UTC)

course_key = CourseKey.from_string(attempt_obj.exam.course_id)
usage_key = UsageKey.from_string(attempt_obj.exam.content_id)
emit_exam_attempt_submitted_event(
attempt_obj.user,
course_key,
usage_key,
attempt_obj.exam.exam_type
)

if to_status == ExamAttemptStatus.verified:
emit_exam_attempt_verified_event(
attempt_obj.user,
course_key,
usage_key,
attempt_obj.exam.exam_type
)

attempt_obj.status = to_status
attempt_obj.save()

Expand Down
16 changes: 15 additions & 1 deletion edx_exams/apps/core/signals/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"""
from django.dispatch import receiver
from openedx_events.event_bus import get_producer
from openedx_events.learning.signals import EXAM_ATTEMPT_SUBMITTED
from openedx_events.learning.signals import EXAM_ATTEMPT_SUBMITTED, EXAM_ATTEMPT_VERIFIED


@receiver(EXAM_ATTEMPT_SUBMITTED)
Expand All @@ -18,3 +18,17 @@ def listen_for_exam_attempt_submitted(sender, signal, **kwargs): # pylint: disa
event_data={'exam_attempt': kwargs['exam_attempt']},
event_metadata=kwargs['metadata'],
)


@receiver(EXAM_ATTEMPT_VERIFIED)
def listen_for_exam_attempt_verified(sender, signal, **kwargs): # pylint: disable=unused-argument
"""
Publish EXAM_ATTEMPT_VERIFIED signal onto the event bus
"""
get_producer().send(
signal=EXAM_ATTEMPT_VERIFIED,
topic='exam-attempt-verified',
event_key_field='exam_attempt.course_key',
event_data={'exam_attempt': kwargs['exam_attempt']},
event_metadata=kwargs['metadata'],
)
28 changes: 27 additions & 1 deletion edx_exams/apps/core/signals/signals.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"""

from openedx_events.learning.data import ExamAttemptData, UserData, UserPersonalData
from openedx_events.learning.signals import EXAM_ATTEMPT_SUBMITTED
from openedx_events.learning.signals import EXAM_ATTEMPT_SUBMITTED, EXAM_ATTEMPT_VERIFIED


def emit_exam_attempt_submitted_event(user, course_key, usage_key, exam_type):
Expand All @@ -30,3 +30,29 @@ def emit_exam_attempt_submitted_event(user, course_key, usage_key, exam_type):
requesting_user=user_data
)
)


def emit_exam_attempt_verified_event(user, course_key, usage_key, exam_type):
"""
Emit the EXAM_ATTEMPT_VERIFIED Open edX event.
"""
name = user.full_name or ''
user_data = UserData(
id=user.id,
is_active=user.is_active,
pii=UserPersonalData(
username=user.username,
email=user.email,
name=name
)
)

# .. event_implemented_name: EXAM_ATTEMPT_VERIFIED
EXAM_ATTEMPT_VERIFIED.send_event(
exam_attempt=ExamAttemptData(
student_user=user_data,
course_key=course_key,
usage_key=usage_key,
exam_type=exam_type
)
)
29 changes: 28 additions & 1 deletion edx_exams/apps/core/tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ def test_start_attempt_with_due_date(self, is_due_during_exam):
resource_id=str(uuid.uuid4()),
course_id=self.course_id,
provider=self.test_provider,
content_id='abcd1234',
content_id='block-v1:edX+test+2023+type@sequential+block@1111111111',
exam_name='test_exam',
exam_type='proctored',
time_limit_mins=30,
Expand Down Expand Up @@ -328,6 +328,33 @@ def test_submit_attempt_event_emitted(self, mock_event_send):
)
mock_event_send.assert_called_with(exam_attempt=expected_data)

@patch('edx_exams.apps.core.signals.signals.EXAM_ATTEMPT_VERIFIED.send_event')
def test_verified_attempt_event_emitted(self, mock_event_send):
"""
Test that when an exam is verified, the EXAM_ATTEMPT_VERIFIED Open edX event is emitted.
"""
update_attempt_status(self.exam_attempt.id, ExamAttemptStatus.verified)
self.assertEqual(mock_event_send.call_count, 1)

usage_key = UsageKey.from_string(self.exam.content_id)
course_key = CourseKey.from_string(self.exam.course_id)

expected_data = ExamAttemptData(
student_user=UserData(
id=self.user.id,
is_active=self.user.is_active,
pii=UserPersonalData(
username=self.user.username,
email=self.user.email,
name=self.user.full_name
)
),
course_key=course_key,
usage_key=usage_key,
exam_type=self.exam.exam_type,
)
mock_event_send.assert_called_with(exam_attempt=expected_data)

def test_illegal_start(self):
"""
Test that an already started exam cannot be started
Expand Down
2 changes: 1 addition & 1 deletion edx_exams/apps/lti/signals/tests/test_handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def setUp(self):
)

self.course_id = 'course-v1:edx+test+f19'
self.content_id = '11111111'
self.content_id = 'block-v1:edX+test+2023+type@sequential+block@1111111111'

self.exam = Exam.objects.create(
resource_id=str(uuid.uuid4()),
Expand Down
2 changes: 1 addition & 1 deletion edx_exams/apps/lti/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,7 @@ def setUp(self):
super().setUp()

self.course_id = 'course-v1:edx+test+f19'
self.content_id = '11111111'
self.content_id = 'block-v1:edX+test+2023+type@sequential+block@1111111111'

self.exam = ExamFactory(
course_id=self.course_id,
Expand Down
Loading