Skip to content

Commit 078e4b5

Browse files
committed
fix: Added review suggestions
1 parent 52289b0 commit 078e4b5

File tree

10 files changed

+96
-108
lines changed

10 files changed

+96
-108
lines changed

openedx/core/djangoapps/notifications/config/waffle.py

+2-12
Original file line numberDiff line numberDiff line change
@@ -50,23 +50,13 @@
5050
# .. toggle_tickets: INF-1472
5151
ENABLE_NOTIFICATION_GROUPING = CourseWaffleFlag(f'{WAFFLE_NAMESPACE}.enable_notification_grouping', __name__)
5252

53-
# .. toggle_name: notifications.enable_new_notification_view
54-
# .. toggle_implementation: WaffleFlag
55-
# .. toggle_default: False
56-
# .. toggle_description: Waffle flag to enable new notification view
57-
# .. toggle_use_cases: temporary, open_edx
58-
# .. toggle_creation_date: 2024-09-30
59-
# .. toggle_target_removal_date: 2025-10-10
60-
# .. toggle_tickets: INF-1603
61-
ENABLE_NEW_NOTIFICATION_VIEW = WaffleFlag(f"{WAFFLE_NAMESPACE}.enable_new_notification_view", __name__)
62-
6353
# .. toggle_name: notifications.enable_push_notifications
64-
# .. toggle_implementation: WaffleFlag
54+
# .. toggle_implementation: CourseWaffleFlag
6555
# .. toggle_default: False
6656
# .. toggle_description: Waffle flag to enable push Notifications feature on mobile devices
6757
# .. toggle_use_cases: temporary, open_edx
6858
# .. toggle_creation_date: 2025-02-11
6959
# .. toggle_target_removal_date: 2026-02-11
7060
# .. toggle_warning: When the flag is ON, Notifications will go through using braze on mobile devices.
7161
# .. toggle_tickets: LEARNER-10298
72-
ENABLE_PUSH_NOTIFICATIONS = WaffleFlag(f'{WAFFLE_NAMESPACE}.enable_push_notifications', __name__)
62+
ENABLE_PUSH_NOTIFICATIONS = CourseWaffleFlag(f'{WAFFLE_NAMESPACE}.enable_push_notifications', __name__)

openedx/core/djangoapps/notifications/push/tasks.py

+6-3
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,18 @@ def send_ace_msg_to_braze_push_channel(audience_ids, notification_object, sender
3131
}
3232
emails = list(User.objects.filter(id__in=audience_ids).values_list('email', flat=True))
3333
context = {'post_data': post_data}
34-
35-
sender = User.objects.get(id=sender_id)
36-
recipient = Recipient(sender.id, sender.email)
34+
try:
35+
sender = User.objects.get(id=sender_id)
36+
recipient = Recipient(sender.id, sender.email)
37+
except User.DoesNotExist:
38+
recipient = None
3739

3840
message = PushNotificationMessageType(
3941
app_label="notifications", name="braze_push"
4042
).personalize(recipient, 'en', context)
4143
message.options['emails'] = emails
4244
message.options['braze_campaign'] = notification_type
45+
message.options['skip_disable_user_policy'] = True
4346

4447
ace.send(message, limit_to_channels=[ChannelType.BRAZE_PUSH])
4548
logger.info('Sent mobile notification for %s to ace channel', notification_type)

openedx/core/djangoapps/notifications/push/tests/__init__.py

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
"""
2+
Tests for braze push notifications tasks.
3+
"""
4+
from unittest import mock
5+
6+
from common.djangoapps.student.tests.factories import UserFactory
7+
from openedx.core.djangoapps.notifications.push.tasks import send_ace_msg_to_braze_push_channel
8+
from openedx.core.djangoapps.notifications.tests.utils import create_notification
9+
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
10+
from xmodule.modulestore.tests.factories import CourseFactory
11+
12+
13+
class SendNotificationsTest(ModuleStoreTestCase):
14+
"""
15+
Tests for send_notifications.
16+
"""
17+
18+
def setUp(self):
19+
"""
20+
Create a course and users for the course.
21+
"""
22+
23+
super().setUp()
24+
self.user_1 = UserFactory()
25+
self.user_2 = UserFactory()
26+
self.course_1 = CourseFactory.create(
27+
org='testorg',
28+
number='testcourse',
29+
run='testrun'
30+
)
31+
32+
self.notification = create_notification(
33+
self.user, self.course_1.id, app_name='discussion', notification_type='new_comment'
34+
)
35+
36+
@mock.patch('openedx.core.djangoapps.notifications.push.tasks.ace.send')
37+
def test_send_ace_msg_success(self, mock_ace_send):
38+
""" Test send_ace_msg_success """
39+
send_ace_msg_to_braze_push_channel(
40+
[self.user_1.id, self.user_2.id],
41+
self.notification,
42+
sender_id=self.user_1.id
43+
)
44+
45+
mock_ace_send.assert_called_once()
46+
message_sent = mock_ace_send.call_args[0][0]
47+
assert message_sent.options['emails'] == [self.user_1.email, self.user_2.email]
48+
assert message_sent.options['braze_campaign'] == 'new_comment'
49+
50+
@mock.patch('openedx.core.djangoapps.notifications.push.tasks.ace.send')
51+
def test_send_ace_msg_no_sender(self, mock_ace_send):
52+
""" Test when sender is not valid """
53+
send_ace_msg_to_braze_push_channel(
54+
[self.user_1.id, self.user_2.id],
55+
self.notification,
56+
sender_id=999
57+
)
58+
59+
mock_ace_send.assert_called_once()
60+
61+
@mock.patch('openedx.core.djangoapps.notifications.push.tasks.ace.send')
62+
def test_send_ace_msg_empty_audience(self, mock_ace_send):
63+
""" Test send_ace_msg_success with empty audience """
64+
send_ace_msg_to_braze_push_channel([], self.notification, sender_id=self.user_1.id)
65+
mock_ace_send.assert_not_called()
66+
67+
@mock.patch('openedx.core.djangoapps.notifications.push.tasks.ace.send')
68+
def test_send_ace_msg_non_discussion_app(self, mock_ace_send):
69+
""" Test send_ace_msg_success with non-discussion app """
70+
self.notification.app_name = 'ecommerce'
71+
self.notification.save()
72+
send_ace_msg_to_braze_push_channel([1], self.notification, sender_id=self.user_1.id)
73+
mock_ace_send.assert_not_called()

openedx/core/djangoapps/notifications/tasks.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,9 @@
2626
)
2727
from openedx.core.djangoapps.notifications.events import notification_generated_event
2828
from openedx.core.djangoapps.notifications.grouping_notifications import (
29+
NotificationRegistry,
2930
get_user_existing_notifications,
30-
group_user_notifications, NotificationRegistry,
31+
group_user_notifications
3132
)
3233
from openedx.core.djangoapps.notifications.models import (
3334
CourseNotificationPreference,
@@ -37,7 +38,6 @@
3738
from openedx.core.djangoapps.notifications.push.tasks import send_ace_msg_to_braze_push_channel
3839
from openedx.core.djangoapps.notifications.utils import clean_arguments, get_list_in_batches
3940

40-
4141
logger = get_task_logger(__name__)
4242

4343

@@ -125,6 +125,7 @@ def send_notifications(user_ids, course_key: str, app_name, notification_type, c
125125
"""
126126
Send notifications to the users.
127127
"""
128+
# pylint: disable=too-many-statements
128129
course_key = CourseKey.from_string(course_key)
129130
if not ENABLE_NOTIFICATIONS.is_enabled(course_key):
130131
return
@@ -143,7 +144,7 @@ def send_notifications(user_ids, course_key: str, app_name, notification_type, c
143144
default_web_config = get_default_values_of_preference(app_name, notification_type).get('web', False)
144145
generated_notification_audience = []
145146
push_notification_audience = []
146-
is_push_notification_enabled = ENABLE_PUSH_NOTIFICATIONS.is_enabled()
147+
is_push_notification_enabled = ENABLE_PUSH_NOTIFICATIONS.is_enabled(course_key)
147148

148149
if group_by_id and not grouping_enabled:
149150
logger.info(

openedx/core/djangoapps/notifications/tests/test_tasks.py

+7-86
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,14 @@
99
from django.conf import settings
1010
from django.core.exceptions import ValidationError
1111
from edx_toggles.toggles.testutils import override_waffle_flag
12-
from testfixtures import LogCapture
1312

1413
from common.djangoapps.student.models import CourseEnrollment
1514
from common.djangoapps.student.tests.factories import UserFactory
1615
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase
1716
from xmodule.modulestore.tests.factories import CourseFactory
1817

19-
from ..config.waffle import ENABLE_NOTIFICATIONS, ENABLE_NOTIFICATION_GROUPING, ENABLE_PUSH_NOTIFICATIONS
20-
from ..models import CourseNotificationPreference, Notification, NotificationBrazeCampaigns
18+
from ..config.waffle import ENABLE_NOTIFICATION_GROUPING, ENABLE_NOTIFICATIONS, ENABLE_PUSH_NOTIFICATIONS
19+
from ..models import CourseNotificationPreference, Notification
2120
from ..tasks import (
2221
create_notification_pref_if_not_exists,
2322
delete_notifications,
@@ -26,8 +25,6 @@
2625
)
2726
from .utils import create_notification
2827

29-
LOGGER_NAME = 'openedx.core.djangoapps.notifications.tasks'
30-
3128

3229
@patch('openedx.core.djangoapps.notifications.models.COURSE_NOTIFICATION_CONFIG_VERSION', 1)
3330
class TestNotificationsTasks(ModuleStoreTestCase):
@@ -234,7 +231,6 @@ def test_send_notification_with_grouping_enabled(self):
234231
user_notifications_mock.assert_called_once()
235232

236233
@override_waffle_flag(ENABLE_NOTIFICATIONS, active=True)
237-
@override_waffle_flag(ENABLE_PUSH_NOTIFICATIONS, active=True)
238234
@ddt.data(
239235
('discussion', 'new_comment_on_response'), # core notification
240236
('discussion', 'new_response'), # non core notification
@@ -261,7 +257,6 @@ def test_send_with_app_disabled_notifications(self, app_name, notification_type)
261257
self.assertIsNone(notification)
262258

263259
@override_waffle_flag(ENABLE_NOTIFICATIONS, active=True)
264-
@override_waffle_flag(ENABLE_PUSH_NOTIFICATIONS, active=True)
265260
def test_notification_not_created_when_context_is_incomplete(self):
266261
try:
267262
send_notifications([self.user.id], str(self.course_1.id), "discussion", "new_comment", {}, "")
@@ -299,11 +294,10 @@ def _create_users(self, num_of_users):
299294
return users
300295

301296
@override_waffle_flag(ENABLE_NOTIFICATIONS, active=True)
302-
@override_waffle_flag(ENABLE_PUSH_NOTIFICATIONS, active=True)
303297
@ddt.data(
304-
(settings.NOTIFICATION_CREATION_BATCH_SIZE, 10, 6),
305-
(settings.NOTIFICATION_CREATION_BATCH_SIZE + 10, 12, 9),
306-
(settings.NOTIFICATION_CREATION_BATCH_SIZE - 10, 10, 5),
298+
(settings.NOTIFICATION_CREATION_BATCH_SIZE, 13, 6),
299+
(settings.NOTIFICATION_CREATION_BATCH_SIZE + 10, 15, 9),
300+
(settings.NOTIFICATION_CREATION_BATCH_SIZE - 10, 13, 5),
307301
)
308302
@ddt.unpack
309303
def test_notification_is_send_in_batch(self, creation_size, prefs_query_count, notifications_query_count):
@@ -354,7 +348,7 @@ def test_preference_not_created_for_default_off_preference(self):
354348
"username": "Test Author"
355349
}
356350
with override_waffle_flag(ENABLE_NOTIFICATIONS, active=True):
357-
with self.assertNumQueries(11):
351+
with self.assertNumQueries(13):
358352
send_notifications(user_ids, str(self.course.id), notification_app, notification_type,
359353
context, "http://test.url")
360354

@@ -374,7 +368,7 @@ def test_preference_created_for_default_on_preference(self):
374368
}
375369
with override_waffle_flag(ENABLE_NOTIFICATIONS, active=True):
376370
with override_waffle_flag(ENABLE_PUSH_NOTIFICATIONS, active=True):
377-
with self.assertNumQueries(13):
371+
with self.assertNumQueries(16):
378372
send_notifications(user_ids, str(self.course.id), notification_app, notification_type,
379373
context, "http://test.url")
380374

@@ -419,79 +413,6 @@ def test_preference_enabled_in_batch_audience(self, notification_type,
419413
send_notifications(user_ids, str(self.course.id), app_name, notification_type, context, content_url)
420414
self.assertEqual(len(Notification.objects.all()), generated_count)
421415

422-
@override_waffle_flag(ENABLE_NOTIFICATIONS, active=True)
423-
@override_waffle_flag(ENABLE_PUSH_NOTIFICATIONS, active=True)
424-
@patch('openedx.core.djangoapps.notifications.tasks.get_braze_client')
425-
def test_mobile_notification_send(self, mock_braze_client):
426-
mock_braze_client = mock_braze_client.return_value
427-
mock_braze_client.send_campaign_message.return_value = None
428-
429-
notification_app = "discussion"
430-
notification_type = "new_response"
431-
users = self._create_users(5)
432-
user_ids = [user.id for user in users]
433-
context = {
434-
"post_title": "Test Post",
435-
"author_name": "Test Author",
436-
"replier_name": "Replier Name"
437-
}
438-
with LogCapture() as log:
439-
send_notifications(user_ids, str(self.course.id), notification_app,
440-
notification_type, context, "https://test.url")
441-
442-
self.assertFalse(mock_braze_client.send_campaign_message.called)
443-
log.check_present(
444-
(
445-
'openedx.core.djangoapps.notifications.models',
446-
'INFO',
447-
'No campaign id found for notification type new_response',
448-
)
449-
)
450-
451-
NotificationBrazeCampaigns.objects.create(notification_type=notification_type, braze_campaign_id="123")
452-
send_notifications(user_ids, str(self.course.id), notification_app,
453-
notification_type, context, "https://test.url")
454-
455-
self.assertTrue(mock_braze_client.send_campaign_message.called)
456-
log.check_present(
457-
(
458-
LOGGER_NAME,
459-
'INFO',
460-
'Sent mobile notification for new_response with Braze',
461-
)
462-
)
463-
464-
@override_waffle_flag(ENABLE_NOTIFICATIONS, active=True)
465-
@override_waffle_flag(ENABLE_PUSH_NOTIFICATIONS, active=True)
466-
@patch('openedx.core.djangoapps.notifications.tasks.get_braze_client')
467-
def test_mobile_notification_braze_error(self, mock_braze_client):
468-
mock_braze_client = mock_braze_client.return_value
469-
mock_braze_client.send_campaign_message.side_effect = Exception("Error")
470-
471-
notification_app = "discussion"
472-
notification_type = "new_response"
473-
users = self._create_users(5)
474-
user_ids = [user.id for user in users]
475-
NotificationBrazeCampaigns.objects.create(notification_type=notification_type, braze_campaign_id="123")
476-
477-
context = {
478-
"post_title": "Test Post",
479-
"author_name": "Test Author",
480-
"replier_name": "Replier Name"
481-
}
482-
with LogCapture() as log:
483-
send_notifications(user_ids, str(self.course.id), notification_app,
484-
notification_type, context, "https://test.url")
485-
486-
self.assertTrue(mock_braze_client.send_campaign_message.called)
487-
log.check_present(
488-
(
489-
LOGGER_NAME,
490-
'ERROR',
491-
'Unable to send mobile notification for new_response with Braze. Reason: Error',
492-
)
493-
)
494-
495416

496417
class TestDeleteNotificationTask(ModuleStoreTestCase):
497418
"""

requirements/edx/base.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -398,7 +398,7 @@ drf-yasg==1.21.10
398398
# via
399399
# django-user-tasks
400400
# edx-api-doc-tools
401-
edx-ace==1.12.1
401+
edx-ace==1.14.0
402402
# via -r requirements/edx/kernel.in
403403
edx-api-doc-tools==2.0.0
404404
# via

requirements/edx/development.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -658,7 +658,7 @@ drf-yasg==1.21.10
658658
# -r requirements/edx/testing.txt
659659
# django-user-tasks
660660
# edx-api-doc-tools
661-
edx-ace==1.12.1
661+
edx-ace==1.14.0
662662
# via
663663
# -r requirements/edx/doc.txt
664664
# -r requirements/edx/testing.txt

requirements/edx/doc.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -482,7 +482,7 @@ drf-yasg==1.21.10
482482
# -r requirements/edx/base.txt
483483
# django-user-tasks
484484
# edx-api-doc-tools
485-
edx-ace==1.12.1
485+
edx-ace==1.14.0
486486
# via -r requirements/edx/base.txt
487487
edx-api-doc-tools==2.0.0
488488
# via

requirements/edx/testing.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -507,7 +507,7 @@ drf-yasg==1.21.10
507507
# -r requirements/edx/base.txt
508508
# django-user-tasks
509509
# edx-api-doc-tools
510-
edx-ace==1.12.1
510+
edx-ace==1.14.0
511511
# via -r requirements/edx/base.txt
512512
edx-api-doc-tools==2.0.0
513513
# via

0 commit comments

Comments
 (0)