From 5fd8dced0c494aec128f084c3f1d56bc2a35b32d Mon Sep 17 00:00:00 2001 From: Julio-Oliveira-Encora Date: Mon, 20 May 2024 14:52:18 -0300 Subject: [PATCH] Moved tests from test_event_rules.py to test_conditions.py. --- netbox/extras/conditions.py | 5 -- netbox/extras/tests/test_conditions.py | 96 +++++++++++++++++++++++++ netbox/extras/tests/test_event_rules.py | 90 ----------------------- 3 files changed, 96 insertions(+), 95 deletions(-) diff --git a/netbox/extras/conditions.py b/netbox/extras/conditions.py index 863397d7f..22ab15417 100644 --- a/netbox/extras/conditions.py +++ b/netbox/extras/conditions.py @@ -136,11 +136,6 @@ class ConditionSet: if type(ruleset) is not dict: raise ValueError(_("Ruleset must be a dictionary, not {ruleset}.").format(ruleset=type(ruleset))) - if len(ruleset) != 1: - raise ValueError(_("Ruleset must have exactly one logical operator (found {ruleset})").format( - ruleset=len(ruleset))) - raise ValueError(f"Ruleset must be a dictionary, not {type(ruleset)}.") - if len(ruleset) == 1: self.logic = (list(ruleset.keys())[0]).lower() if self.logic not in (AND, OR): diff --git a/netbox/extras/tests/test_conditions.py b/netbox/extras/tests/test_conditions.py index e7275482a..dd528b918 100644 --- a/netbox/extras/tests/test_conditions.py +++ b/netbox/extras/tests/test_conditions.py @@ -1,6 +1,12 @@ +from django.contrib.contenttypes.models import ContentType from django.test import TestCase +from dcim.choices import SiteStatusChoices +from dcim.models import Site from extras.conditions import Condition, ConditionSet +from extras.events import serialize_for_event +from extras.forms import EventRuleForm +from extras.models import EventRule, Webhook class ConditionTestCase(TestCase): @@ -217,3 +223,93 @@ class ConditionSetTest(TestCase): self.assertTrue(cs.eval({'a': 1, 'b': 2, 'c': 9})) self.assertFalse(cs.eval({'a': 9, 'b': 2, 'c': 9})) self.assertFalse(cs.eval({'a': 9, 'b': 9, 'c': 3})) + + def test_event_rule_conditions_without_logic_operator(self): + """ + Test evaluation of EventRule conditions without logic operator. + """ + event_rule = EventRule( + name='Event Rule 1', + type_create=True, + type_update=True, + conditions={ + 'attr': 'status.value', + 'value': 'active', + } + ) + + # Create a Site to evaluate - Status = active + site = Site.objects.create(name='Site 1', slug='site-1', status=SiteStatusChoices.STATUS_ACTIVE) + data = serialize_for_event(site) + + # Evaluate the conditions (status='active') + self.assertTrue(event_rule.eval_conditions(data)) + + def test_event_rule_conditions_with_logical_operation(self): + """ + Test evaluation of EventRule conditions without logic operator, but with logical operation (in). + """ + event_rule = EventRule( + name='Event Rule 1', + type_create=True, + type_update=True, + conditions={ + "attr": "status.value", + "value": ["planned", "staging"], + "op": "in", + } + ) + + # Create a Site to evaluate - Status = active + site = Site.objects.create(name='Site 1', slug='site-1', status=SiteStatusChoices.STATUS_ACTIVE) + data = serialize_for_event(site) + + # Evaluate the conditions (status in ['planned, 'staging']) + self.assertFalse(event_rule.eval_conditions(data)) + + def test_event_rule_conditions_with_logical_operation_and_negate(self): + """ + Test evaluation of EventRule with logical operation (in) and negate. + """ + event_rule = EventRule( + name='Event Rule 1', + type_create=True, + type_update=True, + conditions={ + "attr": "status.value", + "value": ["planned", "staging"], + "op": "in", + "negate": True, + } + ) + + # Create a Site to evaluate - Status = active + site = Site.objects.create(name='Site 1', slug='site-1', status=SiteStatusChoices.STATUS_ACTIVE) + data = serialize_for_event(site) + + # Evaluate the conditions (status NOT in ['planned, 'staging']) + self.assertTrue(event_rule.eval_conditions(data)) + + def test_event_rule_conditions_with_incorrect_key_must_return_false(self): + """ + Test Event Rule with incorrect condition (key "foo" is wrong). Must return false. + """ + + ct = ContentType.objects.get(app_label='extras', model='webhook') + site_ct = ContentType.objects.get_for_model(Site) + webhook = Webhook.objects.create(name='Webhook 100', payload_url='http://example.com/?1', http_method='POST') + form = EventRuleForm({ + "name": "Event Rule 1", + "type_create": True, + "type_update": True, + "action_object_type": ct.pk, + "action_type": "webhook", + "action_choice": webhook.pk, + "content_types": [site_ct.pk], + "conditions": { + "foo": "status.value", + "value": "active" + } + }) + + self.assertFalse(form.is_valid()) diff --git a/netbox/extras/tests/test_event_rules.py b/netbox/extras/tests/test_event_rules.py index 46809d38e..d1544a8fd 100644 --- a/netbox/extras/tests/test_event_rules.py +++ b/netbox/extras/tests/test_event_rules.py @@ -378,93 +378,3 @@ class EventRuleTest(APITestCase): # Patch the Session object with our dummy_send() method, then process the webhook for sending with patch.object(Session, 'send', dummy_send) as mock_send: send_webhook(**job.kwargs) - - def test_event_rule_conditions_without_logic_operator(self): - """ - Test evaluation of EventRule conditions without logic operator. - """ - event_rule = EventRule( - name='Event Rule 1', - type_create=True, - type_update=True, - conditions={ - 'attr': 'status.value', - 'value': 'active', - } - ) - - # Create a Site to evaluate - Status = active - site = Site.objects.create(name='Site 1', slug='site-1', status=SiteStatusChoices.STATUS_ACTIVE) - data = serialize_for_event(site) - - # Evaluate the conditions (status='active') - self.assertTrue(event_rule.eval_conditions(data)) - - def test_event_rule_conditions_with_logical_operation(self): - """ - Test evaluation of EventRule conditions without logic operator, but with logical operation (in). - """ - event_rule = EventRule( - name='Event Rule 1', - type_create=True, - type_update=True, - conditions={ - "attr": "status.value", - "value": ["planned", "staging"], - "op": "in", - } - ) - - # Create a Site to evaluate - Status = active - site = Site.objects.create(name='Site 1', slug='site-1', status=SiteStatusChoices.STATUS_ACTIVE) - data = serialize_for_event(site) - - # Evaluate the conditions (status in ['planned, 'staging']) - self.assertFalse(event_rule.eval_conditions(data)) - - def test_event_rule_conditions_with_logical_operation_and_negate(self): - """ - Test evaluation of EventRule with logical operation (in) and negate. - """ - event_rule = EventRule( - name='Event Rule 1', - type_create=True, - type_update=True, - conditions={ - "attr": "status.value", - "value": ["planned", "staging"], - "op": "in", - "negate": True, - } - ) - - # Create a Site to evaluate - Status = active - site = Site.objects.create(name='Site 1', slug='site-1', status=SiteStatusChoices.STATUS_ACTIVE) - data = serialize_for_event(site) - - # Evaluate the conditions (status NOT in ['planned, 'staging']) - self.assertTrue(event_rule.eval_conditions(data)) - - def test_event_rule_conditions_with_incorrect_key_must_return_false(self): - """ - Test Event Rule with incorrect condition (key "foo" is wrong). Must return false. - """ - - ct = ContentType.objects.get(app_label='extras', model='webhook') - site_ct = ContentType.objects.get_for_model(Site) - webhook = Webhook.objects.create(name='Webhook 100', payload_url='http://example.com/?1', http_method='POST') - form = EventRuleForm({ - "name": "Event Rule 1", - "type_create": True, - "type_update": True, - "action_object_type": ct.pk, - "action_type": "webhook", - "action_choice": webhook.pk, - "content_types": [site_ct.pk], - "conditions": { - "foo": "status.value", - "value": "active" - } - }) - - self.assertFalse(form.is_valid())