Add local settings management
Add cellular-first ntfy delivery with WiFi fallback and safe SIM868 HTTP header framing. Co-authored-by: Copilot <[email protected]>
This commit is contained in:
@@ -139,6 +139,122 @@ class NtfyTransportTest(unittest.TestCase):
|
||||
)
|
||||
response.raise_for_status.assert_called_once_with()
|
||||
|
||||
@patch("modules.app_alerts.app_cellular.http_post")
|
||||
@patch(
|
||||
"modules.app_alerts.app_cellular.is_configured",
|
||||
return_value=True,
|
||||
)
|
||||
@patch("modules.app_alerts.requests.post")
|
||||
def test_cellular_is_primary_when_configured(
|
||||
self,
|
||||
post,
|
||||
_is_configured,
|
||||
cellular_post,
|
||||
):
|
||||
cellular_post.return_value = (200, b"ok")
|
||||
|
||||
app_alerts.send_ntfy(
|
||||
"https://ntfy.example/topic",
|
||||
"secret",
|
||||
"Alert title",
|
||||
"Alert body",
|
||||
"high",
|
||||
["warning"],
|
||||
)
|
||||
|
||||
cellular_post.assert_called_once_with(
|
||||
"https://ntfy.example/topic",
|
||||
b"Alert body",
|
||||
{
|
||||
"Title": "Alert title",
|
||||
"Priority": "high",
|
||||
"Tags": "warning",
|
||||
"Authorization": "Bearer secret",
|
||||
},
|
||||
content_type="text/plain; charset=utf-8",
|
||||
)
|
||||
post.assert_not_called()
|
||||
|
||||
@patch("modules.app_alerts.app_cellular.http_post")
|
||||
@patch(
|
||||
"modules.app_alerts.app_cellular.is_configured",
|
||||
return_value=True,
|
||||
)
|
||||
@patch("modules.app_alerts.requests.post")
|
||||
def test_cellular_http_error_falls_back_to_wifi(
|
||||
self,
|
||||
post,
|
||||
_is_configured,
|
||||
cellular_post,
|
||||
):
|
||||
cellular_post.return_value = (503, b"error")
|
||||
post.return_value.raise_for_status.return_value = None
|
||||
|
||||
app_alerts.send_ntfy(
|
||||
"https://ntfy.example/topic",
|
||||
"",
|
||||
"Alert title",
|
||||
"Alert body",
|
||||
)
|
||||
|
||||
cellular_post.assert_called_once()
|
||||
post.assert_called_once()
|
||||
|
||||
@patch("modules.app_alerts.app_cellular.http_post")
|
||||
@patch(
|
||||
"modules.app_alerts.app_cellular.is_configured",
|
||||
return_value=True,
|
||||
)
|
||||
@patch("modules.app_alerts.requests.post")
|
||||
def test_wifi_error_is_reported_after_cellular_failure(
|
||||
self,
|
||||
post,
|
||||
_is_configured,
|
||||
cellular_post,
|
||||
):
|
||||
cellular_post.side_effect = app_alerts.app_cellular.CellularError(
|
||||
"modem offline"
|
||||
)
|
||||
post.side_effect = requests.ReadTimeout("response timed out")
|
||||
|
||||
with self.assertRaises(requests.ReadTimeout):
|
||||
app_alerts.send_ntfy(
|
||||
"https://ntfy.example/topic",
|
||||
"",
|
||||
"Alert title",
|
||||
"Alert body",
|
||||
)
|
||||
|
||||
cellular_post.assert_called_once()
|
||||
|
||||
@patch("modules.app_alerts.app_cellular.http_post")
|
||||
@patch(
|
||||
"modules.app_alerts.app_cellular.is_configured",
|
||||
return_value=True,
|
||||
)
|
||||
@patch("modules.app_alerts.requests.post")
|
||||
def test_both_transport_failures_do_not_expose_private_url(
|
||||
self,
|
||||
post,
|
||||
_is_configured,
|
||||
cellular_post,
|
||||
):
|
||||
post.side_effect = requests.ConnectionError("offline")
|
||||
cellular_post.return_value = (503, b"error")
|
||||
|
||||
with self.assertRaises(requests.ConnectionError) as raised:
|
||||
app_alerts.send_ntfy(
|
||||
"https://ntfy.example/private-topic",
|
||||
"",
|
||||
"Alert title",
|
||||
"Alert body",
|
||||
)
|
||||
|
||||
self.assertEqual(
|
||||
app_alerts._transport_error(raised.exception),
|
||||
"Notification connection failed",
|
||||
)
|
||||
|
||||
def test_transport_error_does_not_expose_url(self):
|
||||
response = requests.Response()
|
||||
response.status_code = 401
|
||||
|
||||
Reference in New Issue
Block a user