Skip to content

Commit 1c10f59

Browse files
committed
[fix] Fixed regression in connection notifications #269
- notifications should not be generated when is_working is None (new device) - tests were not running because were not inheriting TestCase, hence the code was not properly ported Related to #269
1 parent 488a40f commit 1c10f59

File tree

2 files changed

+57
-14
lines changed

2 files changed

+57
-14
lines changed

openwisp_controller/connection/apps.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,13 @@ def _is_update_in_progress(cls, device_pk):
7575
return False
7676

7777
@classmethod
78-
def is_working_changed_receiver(cls, instance, is_working, **kwargs):
78+
def is_working_changed_receiver(
79+
cls, instance, is_working, old_is_working, **kwargs
80+
):
81+
# if old_is_working is None, it's a new device connection which wasn't
82+
# used yet, so nothing is really changing and we won't notify the user
83+
if old_is_working is None:
84+
return
7985
device = instance.device
8086
notification_opts = dict(sender=instance, target=device)
8187
if not is_working:

openwisp_controller/connection/tests/test_notifications.py

Lines changed: 50 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1+
import os
2+
13
from django.apps.registry import apps
24
from django.core import mail
5+
from django.test import TestCase
36
from django.urls import reverse
47
from django.utils.html import strip_tags
58
from openwisp_notifications.types import unregister_notification_type
@@ -12,7 +15,7 @@
1215
DeviceConnection = load_model('connection', 'DeviceConnection')
1316

1417

15-
class TestNotifications(CreateConnectionsMixin):
18+
class TestNotifications(CreateConnectionsMixin, TestCase):
1619
app_label = 'connection'
1720

1821
def setUp(self):
@@ -21,23 +24,26 @@ def setUp(self):
2124
self.creds = Credentials.objects.create(
2225
connector='openwisp_controller.connection.connectors.ssh.Ssh'
2326
)
24-
self.dc = DeviceConnection.objects.create(credentials=self.creds, device=self.d)
2527

2628
def _generic_notification_test(
2729
self, exp_level, exp_type, exp_verb, exp_message, exp_email_subject
2830
):
2931
n = Notification.objects.first()
3032
url_path = reverse('notifications:notification_read_redirect', args=[n.pk])
3133
exp_email_link = f'https://example.com{url_path}'
32-
exp_target_link = f'https://example.com/admin/config/device/{self.d.id}/change/'
34+
config_app = (
35+
'config' if not os.environ.get('SAMPLE_APP', False) else 'sample_config'
36+
)
37+
device_url_path = reverse(f'admin:{config_app}_device_change', args=[self.d.id])
38+
exp_target_link = f'https://example.com{device_url_path}'
3339
exp_email_body = '{message}' f'\n\nFor more information see {exp_email_link}.'
3440

3541
email = mail.outbox.pop()
3642
html_message, _ = email.alternatives.pop()
3743
self.assertEqual(n.type, exp_type)
3844
self.assertEqual(n.level, exp_level)
3945
self.assertEqual(n.verb, exp_verb)
40-
self.assertEqual(n.actor, self.dc)
46+
self.assertEqual(n.actor, self.d.deviceconnection_set.first())
4147
self.assertEqual(n.target, self.d)
4248
self.assertEqual(
4349
n.message, exp_message.format(n=n, target_link=exp_target_link)
@@ -51,17 +57,17 @@ def _generic_notification_test(
5157
)
5258
self.assertIn(
5359
f'<a href="{exp_email_link}">'
54-
'For further information see "device: default.test.device".</a>',
60+
f'For further information see "device: {n.target}".</a>',
5561
html_message,
5662
)
5763

5864
def test_connection_working_notification(self):
5965
self.assertEqual(Notification.objects.count(), 0)
60-
self.dc = DeviceConnection.objects.create(
66+
device_connection = DeviceConnection.objects.create(
6167
credentials=self.creds, device=self.d, is_working=False
6268
)
63-
self.dc.is_working = True
64-
self.dc.save()
69+
device_connection.is_working = True
70+
device_connection.save()
6571
self.assertEqual(Notification.objects.count(), 1)
6672
self._generic_notification_test(
6773
exp_level='info',
@@ -74,10 +80,36 @@ def test_connection_working_notification(self):
7480
exp_email_subject='[example.com] RECOVERY: Connection to device {n.target}',
7581
)
7682

83+
def test_connection_is_working_none(self):
84+
self.assertEqual(Notification.objects.count(), 0)
85+
86+
with self.subTest('no problem notification created when is_working=None'):
87+
DeviceConnection.objects.all().delete()
88+
device_connection = DeviceConnection.objects.create(
89+
credentials=self.creds, device=self.d, is_working=None
90+
)
91+
self.assertIsNone(device_connection.is_working)
92+
device_connection.is_working = False
93+
device_connection.save()
94+
self.assertEqual(Notification.objects.count(), 0)
95+
96+
with self.subTest('no recovery notification created when is_working=None'):
97+
DeviceConnection.objects.all().delete()
98+
device_connection = DeviceConnection.objects.create(
99+
credentials=self.creds, device=self.d, is_working=None
100+
)
101+
self.assertIsNone(device_connection.is_working)
102+
device_connection.is_working = True
103+
device_connection.save()
104+
self.assertEqual(Notification.objects.count(), 0)
105+
77106
def test_connection_not_working_notification(self):
107+
device_connection = DeviceConnection.objects.create(
108+
credentials=self.creds, device=self.d, is_working=True
109+
)
78110
self.assertEqual(Notification.objects.count(), 0)
79-
self.dc.is_working = False
80-
self.dc.save()
111+
device_connection.is_working = False
112+
device_connection.save()
81113
self.assertEqual(Notification.objects.count(), 1)
82114
self._generic_notification_test(
83115
exp_level='error',
@@ -91,10 +123,15 @@ def test_connection_not_working_notification(self):
91123
)
92124

93125
def test_unreachable_after_upgrade_notification(self):
126+
device_connection = DeviceConnection.objects.create(
127+
credentials=self.creds, device=self.d, is_working=True
128+
)
94129
self.assertEqual(Notification.objects.count(), 0)
95-
self.dc.is_working = False
96-
self.dc.failure_reason = 'Giving up, device not reachable anymore after upgrade'
97-
self.dc.save()
130+
device_connection.is_working = False
131+
device_connection.failure_reason = (
132+
'Giving up, device not reachable anymore after upgrade'
133+
)
134+
device_connection.save()
98135
self.assertEqual(Notification.objects.count(), 1)
99136
self._generic_notification_test(
100137
exp_level='error',

0 commit comments

Comments
 (0)