|
3 | 3 | """ |
4 | 4 |
|
5 | 5 | from unittest import mock |
| 6 | +from unittest.mock import patch |
6 | 7 |
|
| 8 | +import pytest |
7 | 9 | from ccx_keys.locator import CCXLocator |
8 | 10 | from django.utils.timezone import now |
9 | 11 | from openedx_events.learning.data import ( |
|
34 | 36 |
|
35 | 37 | class PersistentGradeEventsTest(OpenEdxEventsTestMixin, SharedModuleStoreTestCase): |
36 | 38 | """ |
37 | | - Tests for the Open edX Events associated with the persistant grade process through the update_or_create method. |
| 39 | + Tests for the Open edX Events associated with the persistent grade process through the update_or_create method. |
38 | 40 |
|
39 | 41 | This class guarantees that the following events are sent during the user updates their grade, with |
40 | 42 | the exact Data Attributes as the event definition stated: |
@@ -229,3 +231,81 @@ def test_ccx_course_passing_status_updated_emitted(self): |
229 | 231 | }, |
230 | 232 | event_receiver.call_args.kwargs, |
231 | 233 | ) |
| 234 | + |
| 235 | + |
| 236 | +class GradeEventContextFilterTest(SharedModuleStoreTestCase): |
| 237 | + """ |
| 238 | + Tests that course_grade_passed_first_time invokes the GradeEventContextRequested |
| 239 | + filter and uses the returned context directly. |
| 240 | + """ |
| 241 | + |
| 242 | + def setUp(self): |
| 243 | + super().setUp() |
| 244 | + self.user = UserFactory.create() |
| 245 | + self.course = CourseFactory.create() |
| 246 | + |
| 247 | + @patch('lms.djangoapps.grades.events.tracker') |
| 248 | + @patch('lms.djangoapps.grades.events.contexts.course_context_from_course_id') |
| 249 | + @patch('lms.djangoapps.grades.events.GradeEventContextRequested.run_filter') |
| 250 | + def test_filter_called_with_context( |
| 251 | + self, |
| 252 | + mock_run_filter, |
| 253 | + mock_course_context_from_course_id, |
| 254 | + mock_tracker, |
| 255 | + ): |
| 256 | + """ |
| 257 | + course_grade_passed_first_time should call |
| 258 | + GradeEventContextRequested.run_filter and use the returned context. |
| 259 | + """ |
| 260 | + original_context = {"course_id": str(self.course.id)} |
| 261 | + filtered_context = { |
| 262 | + "course_id": str(self.course.id), |
| 263 | + "org": "test_org", |
| 264 | + "enterprise_uuid": "abc-123", |
| 265 | + } |
| 266 | + mock_course_context_from_course_id.return_value = original_context |
| 267 | + mock_run_filter.return_value = (filtered_context, self.user.id, self.course.id) |
| 268 | + |
| 269 | + from lms.djangoapps.grades.events import course_grade_passed_first_time |
| 270 | + |
| 271 | + course_grade_passed_first_time(self.user.id, self.course.id) |
| 272 | + |
| 273 | + mock_run_filter.assert_called_once_with( |
| 274 | + context=original_context, |
| 275 | + user_id=self.user.id, |
| 276 | + course_id=self.course.id, |
| 277 | + ) |
| 278 | + mock_tracker.get_tracker.return_value.context.assert_called_once_with( |
| 279 | + 'edx.course.grade.passed.first_time', |
| 280 | + filtered_context, |
| 281 | + ) |
| 282 | + |
| 283 | + @patch('lms.djangoapps.grades.events.log') |
| 284 | + @patch('lms.djangoapps.grades.events.tracker') |
| 285 | + @patch('lms.djangoapps.grades.events.contexts.course_context_from_course_id') |
| 286 | + @patch('lms.djangoapps.grades.events.GradeEventContextRequested.run_filter') |
| 287 | + def test_filter_exception_is_logged_and_raised( |
| 288 | + self, |
| 289 | + mock_run_filter, |
| 290 | + mock_course_context_from_course_id, |
| 291 | + mock_tracker, |
| 292 | + mock_log, |
| 293 | + ): |
| 294 | + """ |
| 295 | + If run_filter raises an exception, it should be logged and re-raised. |
| 296 | + """ |
| 297 | + original_context = {"course_id": str(self.course.id)} |
| 298 | + mock_course_context_from_course_id.return_value = original_context |
| 299 | + mock_run_filter.side_effect = Exception("boom") |
| 300 | + |
| 301 | + from lms.djangoapps.grades.events import course_grade_passed_first_time |
| 302 | + |
| 303 | + with pytest.raises(Exception, match="boom"): |
| 304 | + course_grade_passed_first_time(self.user.id, self.course.id) |
| 305 | + |
| 306 | + mock_log.exception.assert_called_once_with( |
| 307 | + 'GradeEventContextRequested failed for user_id=%s course_id=%s', |
| 308 | + self.user.id, |
| 309 | + self.course.id, |
| 310 | + ) |
| 311 | + mock_tracker.get_tracker.return_value.context.assert_not_called() |
0 commit comments