Skip to content

Commit 005f945

Browse files
test: [FC-0047] add unit tests
1 parent 5e61359 commit 005f945

File tree

1 file changed

+147
-0
lines changed

1 file changed

+147
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
"""
2+
3+
"""
4+
from unittest import TestCase
5+
from unittest.mock import patch, MagicMock
6+
from django.test import override_settings
7+
8+
from firebase_admin.messaging import APNSConfig
9+
10+
from edx_ace.channel.push_notification import PushNotificationChannel
11+
from edx_ace.errors import FatalChannelDeliveryError
12+
from edx_ace.message import Message
13+
from edx_ace.recipient import Recipient
14+
from edx_ace.renderers import RenderedPushNotification
15+
from edx_ace.utils.date import get_current_time
16+
17+
18+
class TestPushNotificationChannel(TestCase):
19+
"""
20+
Tests for the PushNotificationChannel class.
21+
"""
22+
23+
def setUp(self):
24+
super().setUp()
25+
self.lms_user_id = 123
26+
self.msg_kwargs = {
27+
'app_label': 'test_app_label',
28+
'name': 'test_message',
29+
'expiration_time': get_current_time(),
30+
'context': {
31+
'key1': 'value1',
32+
'key2': 'value2',
33+
},
34+
'recipient': Recipient(
35+
lms_user_id=self.lms_user_id,
36+
)
37+
}
38+
39+
@override_settings(PUSH_NOTIFICATIONS_SETTINGS={'CONFIG': 'push_notifications.conf.AppConfig'})
40+
def test_enabled(self):
41+
"""
42+
Test that the channel is enabled when the settings are configured.
43+
"""
44+
self.assertTrue(PushNotificationChannel.enabled())
45+
46+
@override_settings(PUSH_NOTIFICATIONS_SETTINGS=None)
47+
def test_disabled(self):
48+
"""
49+
Test that the channel is disabled when the settings are not configured.
50+
"""
51+
self.assertFalse(PushNotificationChannel.enabled())
52+
53+
@patch('edx_ace.channel.push_notification.LOG')
54+
@patch('edx_ace.channel.push_notification.PushNotificationChannel.send_message')
55+
def test_deliver_no_device_tokens(self, mock_send_message, mock_log):
56+
"""
57+
Test that the deliver method logs a message when the recipient has no push tokens.
58+
"""
59+
with patch.object(PushNotificationChannel, 'get_user_device_tokens', return_value=[]):
60+
message = Message(options={}, **self.msg_kwargs)
61+
rendered_message = RenderedPushNotification(title='Test', body='This is a test.')
62+
63+
channel = PushNotificationChannel()
64+
channel.deliver(message, rendered_message)
65+
66+
mock_log.info.assert_called_with(
67+
'Recipient with ID %s has no push token. Skipping push notification.',
68+
self.lms_user_id
69+
)
70+
mock_send_message.assert_not_called()
71+
72+
@patch('edx_ace.channel.push_notification.PushNotificationChannel.send_message')
73+
def test_deliver_with_device_tokens(self, mock_send_message):
74+
"""
75+
Test that the deliver method sends a push notification for each device token.
76+
"""
77+
with patch.object(PushNotificationChannel, 'get_user_device_tokens', return_value=['token1', 'token2']):
78+
message = Message(options={}, **self.msg_kwargs)
79+
rendered_message = RenderedPushNotification(title='Test', body='This is a test.')
80+
81+
channel = PushNotificationChannel()
82+
channel.deliver(message, rendered_message)
83+
84+
self.assertEqual(mock_send_message.call_count, 2)
85+
86+
@override_settings(FCM_APP_NAME='test_app')
87+
@patch('edx_ace.channel.push_notification.send_message')
88+
@patch('edx_ace.channel.push_notification.dict_to_fcm_message')
89+
@patch('edx_ace.channel.push_notification.PushNotificationChannel.collect_apns_config')
90+
def test_send_message_success(self, mock_collect_apns_config, mock_dict_to_fcm_message, mock_send_message):
91+
"""
92+
Test that the send_message method sends a push notification successfully.
93+
"""
94+
mock_dict_to_fcm_message.return_value = MagicMock()
95+
mock_collect_apns_config.return_value = MagicMock()
96+
97+
message = Message(options={}, **self.msg_kwargs)
98+
rendered_message = RenderedPushNotification(title='Test', body='This is a test.')
99+
100+
channel = PushNotificationChannel()
101+
channel.send_message(message, 'token', rendered_message)
102+
103+
mock_send_message.assert_called_once()
104+
105+
@override_settings(FCM_APP_NAME='test_app')
106+
@patch('edx_ace.channel.push_notification.send_message', side_effect=FatalChannelDeliveryError('Error'))
107+
@patch('edx_ace.channel.push_notification.dict_to_fcm_message')
108+
@patch('edx_ace.channel.push_notification.PushNotificationChannel.collect_apns_config')
109+
@patch('edx_ace.channel.push_notification.LOG')
110+
def test_send_message_failure(
111+
self, mock_log, mock_collect_apns_config, mock_dict_to_fcm_message, mock_send_message
112+
):
113+
"""
114+
Test that the send_message method logs an exception when an error occurs while sending the message.
115+
"""
116+
mock_dict_to_fcm_message.return_value = MagicMock()
117+
mock_collect_apns_config.return_value = MagicMock()
118+
119+
message = Message(options={}, **self.msg_kwargs)
120+
rendered_message = RenderedPushNotification(title='Test', body='This is a test.')
121+
122+
channel = PushNotificationChannel()
123+
124+
with self.assertRaises(FatalChannelDeliveryError):
125+
channel.send_message(message, 'token', rendered_message)
126+
127+
mock_send_message.assert_called_with('token', mock_dict_to_fcm_message.return_value, 'test_app')
128+
mock_log.exception.assert_called_with('Failed to send push notification to %s', 'token')
129+
130+
def test_collect_apns_config(self):
131+
"""
132+
Test that the collect_apns_config method returns an APNSConfig object with the correct headers.
133+
"""
134+
notification_data = {'title': 'Test Title', 'body': 'Test Body'}
135+
136+
apns_config = PushNotificationChannel.collect_apns_config(notification_data)
137+
138+
self.assertIsInstance(apns_config, APNSConfig)
139+
self.assertEqual(apns_config.headers['apns-priority'], '5')
140+
self.assertEqual(apns_config.headers['apns-push-type'], 'alert')
141+
142+
def test_compress_spaces(self):
143+
"""
144+
Test that the compress_spaces method removes extra spaces and newlines from a string.
145+
"""
146+
compressed = PushNotificationChannel.compress_spaces('This is a \n\n test.')
147+
self.assertEqual(compressed, 'This is a test.')

0 commit comments

Comments
 (0)