From 1f70959fa1d36ad7f008e13459b23a72ea6302b0 Mon Sep 17 00:00:00 2001 From: Hussain Nagaria Date: Wed, 14 Apr 2021 05:39:31 +0530 Subject: [PATCH 1/3] feat: Add Enable/Disable Webhook via Check - Added a new field to Webhook DocType - Modfied the webhook run logic to only fetch enabled webhooks --- frappe/integrations/doctype/webhook/__init__.py | 4 +++- frappe/integrations/doctype/webhook/webhook.json | 9 ++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/frappe/integrations/doctype/webhook/__init__.py b/frappe/integrations/doctype/webhook/__init__.py index 8b08db5f68..0524cd609b 100644 --- a/frappe/integrations/doctype/webhook/__init__.py +++ b/frappe/integrations/doctype/webhook/__init__.py @@ -21,7 +21,9 @@ def run_webhooks(doc, method): if webhooks is None: # query webhooks webhooks_list = frappe.get_all('Webhook', - fields=["name", "`condition`", "webhook_docevent", "webhook_doctype"]) + fields=["name", "`condition`", "webhook_docevent", "webhook_doctype"], + filters={"enabled": "1"} + ) # make webhooks map for cache webhooks = {} diff --git a/frappe/integrations/doctype/webhook/webhook.json b/frappe/integrations/doctype/webhook/webhook.json index 9f979099c9..85895c052c 100644 --- a/frappe/integrations/doctype/webhook/webhook.json +++ b/frappe/integrations/doctype/webhook/webhook.json @@ -11,6 +11,7 @@ "webhook_doctype", "cb_doc_events", "webhook_docevent", + "enabled", "sb_condition", "condition", "cb_condition", @@ -147,10 +148,16 @@ "fieldname": "webhook_secret", "fieldtype": "Password", "label": "Webhook Secret" + }, + { + "default": "1", + "fieldname": "enabled", + "fieldtype": "Check", + "label": "Enabled" } ], "links": [], - "modified": "2020-01-13 01:53:04.459968", + "modified": "2021-04-14 05:35:28.532049", "modified_by": "Administrator", "module": "Integrations", "name": "Webhook", From 2133777c4449532263f824c39c2d57452bf63b06 Mon Sep 17 00:00:00 2001 From: Hussain Nagaria Date: Thu, 15 Apr 2021 07:46:39 +0530 Subject: [PATCH 2/3] test: Execute enabled webhook trigger --- .../integrations/doctype/webhook/__init__.py | 2 +- .../doctype/webhook/test_webhook.py | 65 +++++++++++++++++++ 2 files changed, 66 insertions(+), 1 deletion(-) diff --git a/frappe/integrations/doctype/webhook/__init__.py b/frappe/integrations/doctype/webhook/__init__.py index 0524cd609b..19233bd175 100644 --- a/frappe/integrations/doctype/webhook/__init__.py +++ b/frappe/integrations/doctype/webhook/__init__.py @@ -22,7 +22,7 @@ def run_webhooks(doc, method): # query webhooks webhooks_list = frappe.get_all('Webhook', fields=["name", "`condition`", "webhook_docevent", "webhook_doctype"], - filters={"enabled": "1"} + filters={"enabled": True} ) # make webhooks map for cache diff --git a/frappe/integrations/doctype/webhook/test_webhook.py b/frappe/integrations/doctype/webhook/test_webhook.py index fa7f9534e1..6c6e4c1a4d 100644 --- a/frappe/integrations/doctype/webhook/test_webhook.py +++ b/frappe/integrations/doctype/webhook/test_webhook.py @@ -10,6 +10,44 @@ from frappe.integrations.doctype.webhook.webhook import get_webhook_headers, get class TestWebhook(unittest.TestCase): + @classmethod + def setUpClass(cls): + # delete any existing webhooks + frappe.db.sql("DELETE FROM tabWebhook") + # create test webhooks + cls.create_sample_webhooks() + + @classmethod + def create_sample_webhooks(cls): + samples_webhooks_data = [ + { + "webhook_doctype": "User", + "webhook_docevent": "after_insert", + "request_url": "https://httpbin.org/post", + "condition": "doc.email", + "enabled": True + }, + { + "webhook_doctype": "User", + "webhook_docevent": "after_insert", + "request_url": "https://httpbin.org/post", + "condition": "doc.first_name", + "enabled": False + } + ] + + cls.sample_webhooks = [] + for wh_fields in samples_webhooks_data: + wh = frappe.new_doc("Webhook") + wh.update(wh_fields) + wh.insert() + cls.sample_webhooks.append(wh) + + @classmethod + def tearDownClass(cls): + # delete any existing webhooks + frappe.db.sql("DELETE FROM tabWebhook") + def setUp(self): # retrieve or create a User webhook for `after_insert` webhook_fields = { @@ -30,10 +68,37 @@ class TestWebhook(unittest.TestCase): self.user.email = frappe.mock("email") self.user.save() + # Create another test user specific to this test + self.test_user = frappe.new_doc("User") + self.test_user.email = "user1@integration.webhooks.test.com" + self.test_user.first_name = "user1" + def tearDown(self) -> None: self.user.delete() + self.test_user.delete() super().tearDown() + def test_webhook_trigger_with_enabled_webhooks(self): + """Test webhook trigger for enabled webhooks""" + + frappe.cache().delete_value('webhooks') + frappe.flags.webhooks = None + + # Insert the user to db + self.test_user.insert() + + self.assertTrue("User" in frappe.flags.webhooks) + # only 1 hook (enabled) must be queued + self.assertEqual( + len(frappe.flags.webhooks.get("User")), + 1 + ) + self.assertTrue(self.test_user.email in frappe.flags.webhooks_executed) + self.assertEqual( + frappe.flags.webhooks_executed.get(self.test_user.email)[0], + self.sample_webhooks[0].name + ) + def test_validate_doc_events(self): "Test creating a submit-related webhook for a non-submittable DocType" From 38ca6fe621a03ba4fa33aefef677c9711f46d945 Mon Sep 17 00:00:00 2001 From: Suraj Shetty <13928957+surajshetty3416@users.noreply.github.com> Date: Thu, 15 Apr 2021 10:23:09 +0530 Subject: [PATCH 3/3] style: Remove extra space --- frappe/integrations/doctype/webhook/test_webhook.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frappe/integrations/doctype/webhook/test_webhook.py b/frappe/integrations/doctype/webhook/test_webhook.py index 6c6e4c1a4d..acf2f609e7 100644 --- a/frappe/integrations/doctype/webhook/test_webhook.py +++ b/frappe/integrations/doctype/webhook/test_webhook.py @@ -38,7 +38,7 @@ class TestWebhook(unittest.TestCase): cls.sample_webhooks = [] for wh_fields in samples_webhooks_data: - wh = frappe.new_doc("Webhook") + wh = frappe.new_doc("Webhook") wh.update(wh_fields) wh.insert() cls.sample_webhooks.append(wh)