diff --git a/CHANGELOG.md b/CHANGELOG.md index 78b8aea2..4c2169a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ All notable changes to this project will be documented in this file. - Fix List-Unsubscribe email header value: add angle brackets - Unsubscribe links serve a form, and require HTTP POST to actually unsubscribe - For webhook integration, validate each header line separately +- Fix "Send Test Notification" for webhooks that only fire on checks going up ## v1.11.0 - 2019-11-22 diff --git a/hc/api/transports.py b/hc/api/transports.py index 7f53cff9..749bc0cf 100644 --- a/hc/api/transports.py +++ b/hc/api/transports.py @@ -221,7 +221,8 @@ class Webhook(HttpTransport): def notify(self, check): spec = self.channel.webhook_spec(check.status) - assert spec["url"] + if not spec["url"]: + return "Empty webhook URL" url = self.prepare(spec["url"], check, urlencode=True) headers = {} diff --git a/hc/front/tests/test_send_test_notification.py b/hc/front/tests/test_send_test_notification.py index 6ddec998..0b95aca1 100644 --- a/hc/front/tests/test_send_test_notification.py +++ b/hc/front/tests/test_send_test_notification.py @@ -1,6 +1,9 @@ +import json + from django.core import mail from hc.api.models import Channel from hc.test import BaseTestCase +from mock import patch class SendTestNotificationTestCase(BaseTestCase): @@ -27,3 +30,48 @@ class SendTestNotificationTestCase(BaseTestCase): self.assertEqual(email.to[0], "alice@example.org") self.assertTrue("X-Bounce-Url" in email.extra_headers) self.assertTrue("List-Unsubscribe" in email.extra_headers) + + @patch("hc.api.transports.requests.request") + def test_it_handles_webhooks_with_no_down_url(self, mock_get): + mock_get.return_value.status_code = 200 + + self.channel.kind = "webhook" + self.channel.value = json.dumps( + { + "method_down": "GET", + "url_down": "", + "body_down": "", + "headers_down": {}, + "method_up": "GET", + "url_up": "http://example-url", + "body_up": "", + "headers_up": {}, + } + ) + self.channel.save() + + self.client.login(username="alice@example.org", password="password") + r = self.client.post(self.url, {}, follow=True) + self.assertRedirects(r, "/integrations/") + self.assertContains(r, "Test notification sent!") + + def test_it_handles_webhooks_with_no_urls(self): + self.channel.kind = "webhook" + self.channel.value = json.dumps( + { + "method_down": "GET", + "url_down": "", + "body_down": "", + "headers_down": {}, + "method_up": "GET", + "url_up": "", + "body_up": "", + "headers_up": {}, + } + ) + self.channel.save() + + self.client.login(username="alice@example.org", password="password") + r = self.client.post(self.url, {}, follow=True) + self.assertRedirects(r, "/integrations/") + self.assertContains(r, "Could not send a test notification") diff --git a/hc/front/views.py b/hc/front/views.py index 03b036e7..3b314f39 100644 --- a/hc/front/views.py +++ b/hc/front/views.py @@ -747,6 +747,12 @@ def send_test_notification(request, code): dummy.last_ping = timezone.now() - td(days=1) dummy.n_pings = 42 + if channel.kind == "webhook" and not channel.url_down: + if channel.url_up: + # If we don't have url_down, but do have have url_up then + # send "TEST is UP" notification instead: + dummy.status = "up" + if channel.kind == "email": error = channel.transport.notify(dummy, channel.get_unsub_link()) else: