diff --git a/openedx/core/djangoapps/notifications/tests/test_views.py b/openedx/core/djangoapps/notifications/tests/test_views.py index b094a974aaaa..ae03a6ef29e2 100644 --- a/openedx/core/djangoapps/notifications/tests/test_views.py +++ b/openedx/core/djangoapps/notifications/tests/test_views.py @@ -384,6 +384,140 @@ def test_info_is_not_saved_in_json(self): assert 'info' not in type_prefs.keys() +@override_waffle_flag(ENABLE_NOTIFICATIONS, active=True) +@ddt.ddt +class UserNotificationChannelPreferenceAPITest(ModuleStoreTestCase): + """ + Test for user notification channel preference API. + """ + + def setUp(self): + super().setUp() + self.user = UserFactory() + self.course = CourseFactory.create( + org='testorg', + number='testcourse', + run='testrun' + ) + + course_overview = CourseOverviewFactory.create(id=self.course.id, org='AwesomeOrg') + self.course_enrollment = CourseEnrollment.objects.create( + user=self.user, + course=course_overview, + is_active=True, + mode='audit' + ) + self.client = APIClient() + self.path = reverse('notification-channel-preferences', kwargs={'course_key_string': self.course.id}) + + enrollment_data = CourseEnrollmentData( + user=UserData( + pii=UserPersonalData( + username=self.user.username, + email=self.user.email, + name=self.user.profile.name, + ), + id=self.user.id, + is_active=self.user.is_active, + ), + course=CourseData( + course_key=self.course.id, + display_name=self.course.display_name, + ), + mode=self.course_enrollment.mode, + is_active=self.course_enrollment.is_active, + creation_date=self.course_enrollment.created, + ) + COURSE_ENROLLMENT_CREATED.send_event( + enrollment=enrollment_data + ) + + def _expected_api_response(self, course=None): + """ + Helper method to return expected API response. + """ + if course is None: + course = self.course + response = { + 'id': 1, + 'course_name': 'course-v1:testorg+testcourse+testrun Course', + 'course_id': 'course-v1:testorg+testcourse+testrun', + 'notification_preference_config': { + 'discussion': { + 'enabled': True, + 'core_notification_types': [ + 'new_comment_on_response', + 'new_comment', + 'new_response', + 'response_on_followed_post', + 'comment_on_followed_post' + ], + 'notification_types': { + 'core': { + 'web': True, + 'email': True, + 'push': True, + 'info': 'Notifications for responses and comments on your posts, and the ones you’re ' + 'following, including endorsements to your responses and on your posts.' + }, + 'new_discussion_post': {'web': False, 'email': False, 'push': False, 'info': ''}, + 'new_question_post': {'web': False, 'email': False, 'push': False, 'info': ''}, + }, + 'non_editable': { + 'core': ['web'] + } + } + } + } + if not ENABLE_COURSEWIDE_NOTIFICATIONS.is_enabled(course.id): + app_prefs = response['notification_preference_config']['discussion'] + notification_types = app_prefs['notification_types'] + for notification_type in ['new_discussion_post', 'new_question_post']: + notification_types.pop(notification_type) + return response + + @ddt.data( + ('discussion', 'web', True, status.HTTP_200_OK), + ('discussion', 'web', False, status.HTTP_200_OK), + + ('invalid_notification_app', 'web', False, status.HTTP_400_BAD_REQUEST), + ('discussion', 'invalid_notification_channel', False, status.HTTP_400_BAD_REQUEST), + ) + @ddt.unpack + @mock.patch("eventtracking.tracker.emit") + def test_patch_user_notification_preference( + self, notification_app, notification_channel, value, expected_status, mock_emit, + ): + """ + Test update of user notification channel preference. + """ + self.client.login(username=self.user.username, password=self.TEST_PASSWORD) + payload = { + 'notification_app': notification_app, + 'value': value, + } + if notification_channel: + payload['notification_channel'] = notification_channel + + response = self.client.patch(self.path, json.dumps(payload), content_type='application/json') + self.assertEqual(response.status_code, expected_status) + + if expected_status == status.HTTP_200_OK: + expected_data = self._expected_api_response() + expected_app_prefs = expected_data['notification_preference_config'][notification_app] + for notification_type_name, notification_type_preferences in expected_app_prefs[ + 'notification_types'].items(): + non_editable_channels = expected_app_prefs['non_editable'].get(notification_type_name, []) + if notification_channel not in non_editable_channels: + expected_app_prefs['notification_types'][notification_type_name][notification_channel] = value + self.assertEqual(response.data, expected_data) + event_name, event_data = mock_emit.call_args[0] + self.assertEqual(event_name, 'edx.notifications.preferences.updated') + self.assertEqual(event_data['notification_app'], notification_app) + self.assertEqual(event_data['notification_channel'], notification_channel) + self.assertEqual(event_data['value'], value) + + class NotificationListAPIViewTest(APITestCase): """ Tests suit for the NotificationListAPIView.