Skip to content

Commit b2e2995

Browse files
Integration Rules Test
1 parent d9575d8 commit b2e2995

2 files changed

Lines changed: 193 additions & 105 deletions

File tree

src/rules_validation_api/validators/campaign_config_validator.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@ class CampaignConfigValidation(CampaignConfig):
88
iterations: list[IterationValidation] = Field(..., min_length=1, alias="Iterations")
99

1010
@field_validator("id")
11-
def validate_name(cls, value: str) -> str:
11+
def validate_name(self, value: str) -> str:
1212
if not value.strip():
1313
raise ValueError("campaign ID must not be empty")
1414
return value
1515

1616
@field_validator("type")
17-
def validate_type(cls, value: str) -> str:
17+
def validate_type(self, value: str) -> str:
1818
allowed_values = {"V", "S"}
1919
if value not in allowed_values:
2020
raise ValueError(f"type must be one of {allowed_values}")
Lines changed: 191 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -1,135 +1,223 @@
1-
from datetime import datetime
2-
31
import pytest
42
from pydantic import ValidationError
53

6-
from eligibility_signposting_api.config.contants import RULE_STOP_DEFAULT
7-
from eligibility_signposting_api.model.campaign_config import RuleStop
8-
from rules_validation_api.validators.iteration_validator import IterationValidation
4+
from rules_validation_api.validators.iteration_validator import IterationRuleValidation
95

106

117
class TestMandatoryFieldsSchemaValidations:
128
def test_campaign_config_with_only_mandatory_fields_configuration(
13-
self, valid_iteration_rule_with_only_mandatory_fields
9+
self, valid_iteration_rule_with_only_mandatory_fields
1410
):
1511
try:
16-
IterationValidation(**(valid_iteration_rule_with_only_mandatory_fields["Iterations"][0]))
12+
IterationRuleValidation(**valid_iteration_rule_with_only_mandatory_fields)
1713
except ValidationError as e:
1814
pytest.fail(f"Unexpected error during model instantiation: {e}")
1915

2016
@pytest.mark.parametrize(
2117
"mandatory_field",
22-
[
23-
"Type"
24-
"Name"
25-
"Description"
26-
"Priority"
27-
"AttributeLevel"
28-
"Operator"
29-
"Comparator"
30-
],
18+
["Type", "Name", "Description", "Priority", "AttributeLevel", "Operator", "Comparator"],
3119
)
3220
def test_missing_mandatory_fields(self, mandatory_field, valid_iteration_rule_with_only_mandatory_fields):
33-
data = valid_iteration_rule_with_only_mandatory_fields["Iterations"][0].copy()
21+
data = valid_iteration_rule_with_only_mandatory_fields.copy()
3422
data.pop(mandatory_field, None) # Simulate missing field
3523
with pytest.raises(ValidationError):
36-
IterationValidation(**data)
24+
IterationRuleValidation(**data)
3725
assert mandatory_field.lower()
3826

39-
# Type
40-
def test_missing_type(self, valid_iteration_rule_with_only_mandatory_fields):
27+
@pytest.mark.parametrize("type_value", ["F", "S", "R", "X", "Y"])
28+
def test_valid_type(self, type_value, valid_iteration_rule_with_only_mandatory_fields):
29+
data = valid_iteration_rule_with_only_mandatory_fields.copy()
30+
data["Type"] = type_value
31+
result = IterationRuleValidation(**data)
32+
assert result.type.value == type_value
33+
34+
@pytest.mark.parametrize("type_value", ["Z", 123, None])
35+
def test_invalid_type(self, type_value, valid_iteration_rule_with_only_mandatory_fields):
36+
data = valid_iteration_rule_with_only_mandatory_fields.copy()
37+
data["Type"] = type_value
38+
with pytest.raises(ValidationError):
39+
IterationRuleValidation(**data)
40+
41+
@pytest.mark.parametrize("name_value", ["", "ValidName", "Test_Rule_01"])
42+
def test_valid_name(self, name_value, valid_iteration_rule_with_only_mandatory_fields):
43+
data = valid_iteration_rule_with_only_mandatory_fields.copy()
44+
data["Name"] = name_value
45+
result = IterationRuleValidation(**data)
46+
assert result.name == name_value
47+
48+
@pytest.mark.parametrize("name_value", [None, 42])
49+
def test_invalid_name(self, name_value, valid_iteration_rule_with_only_mandatory_fields):
4150
data = valid_iteration_rule_with_only_mandatory_fields.copy()
42-
data.pop("Type", None)
43-
with pytest.raises(ValidationError) as e:
44-
IterationValidation(**data)
45-
assert any(err["loc"][-1] == "Type" for err in e.value.errors())
51+
data["Name"] = name_value
52+
with pytest.raises(ValidationError):
53+
IterationRuleValidation(**data)
4654

47-
# Name
48-
def test_missing_name(self, valid_iteration_rule_with_only_mandatory_fields):
55+
@pytest.mark.parametrize("description_value", ["", "A rule description", "Sample text"])
56+
def test_valid_description(self, description_value, valid_iteration_rule_with_only_mandatory_fields):
4957
data = valid_iteration_rule_with_only_mandatory_fields.copy()
50-
data.pop("Name", None)
51-
with pytest.raises(ValidationError) as e:
52-
IterationValidation(**data)
53-
assert any(err["loc"][-1] == "Name" for err in e.value.errors())
58+
data["Description"] = description_value
59+
result = IterationRuleValidation(**data)
60+
assert result.description == description_value
5461

55-
# Description
56-
def test_missing_description(self, valid_iteration_rule_with_only_mandatory_fields):
62+
@pytest.mark.parametrize("description_value", [None])
63+
def test_invalid_description(self, description_value, valid_iteration_rule_with_only_mandatory_fields):
5764
data = valid_iteration_rule_with_only_mandatory_fields.copy()
58-
data.pop("Description", None)
59-
with pytest.raises(ValidationError) as e:
60-
IterationValidation(**data)
61-
assert any(err["loc"][-1] == "Description" for err in e.value.errors())
65+
data["Description"] = description_value
66+
with pytest.raises(ValidationError):
67+
IterationRuleValidation(**data)
6268

63-
# Priority
64-
def test_missing_priority(self, valid_iteration_rule_with_only_mandatory_fields):
69+
@pytest.mark.parametrize("priority_value", [-1, -5, 1, 100, 999])
70+
def test_valid_priority(self, priority_value, valid_iteration_rule_with_only_mandatory_fields):
6571
data = valid_iteration_rule_with_only_mandatory_fields.copy()
66-
data.pop("Priority", None)
67-
with pytest.raises(ValidationError) as e:
68-
IterationValidation(**data)
69-
assert any(err["loc"][-1] == "Priority" for err in e.value.errors())
72+
data["Priority"] = priority_value
73+
result = IterationRuleValidation(**data)
74+
assert result.priority == priority_value
7075

71-
# AttributeLevel
72-
def test_missing_attribute_level(self, valid_iteration_rule_with_only_mandatory_fields):
76+
@pytest.mark.parametrize("priority_value", ["high", None])
77+
def test_invalid_priority(self, priority_value, valid_iteration_rule_with_only_mandatory_fields):
7378
data = valid_iteration_rule_with_only_mandatory_fields.copy()
74-
data.pop("AttributeLevel", None)
75-
with pytest.raises(ValidationError) as e:
76-
IterationValidation(**data)
77-
assert any(err["loc"][-1] == "AttributeLevel" for err in e.value.errors())
79+
data["Priority"] = priority_value
80+
with pytest.raises(ValidationError):
81+
IterationRuleValidation(**data)
82+
83+
@pytest.mark.parametrize("attribute_level", ["PERSON", "TARGET", "COHORT"])
84+
def test_valid_attribute_level(self, attribute_level, valid_iteration_rule_with_only_mandatory_fields):
85+
data = valid_iteration_rule_with_only_mandatory_fields.copy()
86+
data["AttributeLevel"] = attribute_level
87+
result = IterationRuleValidation(**data)
88+
assert result.attribute_level == attribute_level
89+
90+
@pytest.mark.parametrize("attribute_level", ["", None, 42, "basic", "BASIC"])
91+
def test_invalid_attribute_level(self, attribute_level, valid_iteration_rule_with_only_mandatory_fields):
92+
data = valid_iteration_rule_with_only_mandatory_fields.copy()
93+
data["AttributeLevel"] = attribute_level
94+
with pytest.raises(ValidationError):
95+
IterationRuleValidation(**data)
96+
97+
@pytest.mark.parametrize("operator_value", ["=", "!=", ">", "<=", "contains", "is_true"])
98+
def test_valid_operator(self, operator_value, valid_iteration_rule_with_only_mandatory_fields):
99+
data = valid_iteration_rule_with_only_mandatory_fields.copy()
100+
data["Operator"] = operator_value
101+
result = IterationRuleValidation(**data)
102+
assert result.operator.value == operator_value
103+
104+
@pytest.mark.parametrize("operator_value", ["approx", "", None])
105+
def test_invalid_operator(self, operator_value, valid_iteration_rule_with_only_mandatory_fields):
106+
data = valid_iteration_rule_with_only_mandatory_fields.copy()
107+
data["Operator"] = operator_value
108+
with pytest.raises(ValidationError):
109+
IterationRuleValidation(**data)
110+
111+
@pytest.mark.parametrize("comparator_value", ["status", "true", "0"])
112+
def test_valid_comparator(self, comparator_value, valid_iteration_rule_with_only_mandatory_fields):
113+
data = valid_iteration_rule_with_only_mandatory_fields.copy()
114+
data["Comparator"] = comparator_value
115+
result = IterationRuleValidation(**data)
116+
assert result.comparator == comparator_value
117+
118+
@pytest.mark.parametrize("comparator_value", [None, 123])
119+
def test_invalid_comparator(self, comparator_value, valid_iteration_rule_with_only_mandatory_fields):
120+
data = valid_iteration_rule_with_only_mandatory_fields.copy()
121+
data["Comparator"] = comparator_value
122+
with pytest.raises(ValidationError):
123+
IterationRuleValidation(**data)
78124

79125

80126
class TestOptionalFieldsSchemaValidations:
81-
# AttributeName
82-
def test_attribute_name_accepts_value(self, valid_iteration_rule_with_only_mandatory_fields):
83-
data = {**valid_iteration_rule_with_only_mandatory_fields, "AttributeName": "LAST_SUCCESSFUL_DATE"}
84-
model = IterationValidation(**data)
85-
assert model.attribute_name == "LAST_SUCCESSFUL_DATE"
86-
87-
def test_attribute_name_accepts_none(self, valid_iteration_rule_with_only_mandatory_fields):
88-
data = {**valid_iteration_rule_with_only_mandatory_fields, "AttributeName": None}
89-
model = IterationValidation(**data)
90-
assert model.attribute_name is None
91-
92-
# CohortLabel
93-
def test_cohort_label_accepts_value(self, valid_iteration_rule_with_only_mandatory_fields):
94-
data = {**valid_iteration_rule_with_only_mandatory_fields, "CohortLabel": "elid_all_people"}
95-
model = IterationValidation(**data)
96-
assert model.cohort_label == "elid_all_people"
97-
98-
def test_cohort_label_accepts_none(self, valid_iteration_rule_with_only_mandatory_fields):
99-
data = {**valid_iteration_rule_with_only_mandatory_fields, "CohortLabel": None}
100-
model = IterationValidation(**data)
101-
assert model.cohort_label is None
102-
103-
# AttributeTarget
104-
def test_attribute_target_accepts_value(self, valid_iteration_rule_with_only_mandatory_fields):
105-
data = {**valid_iteration_rule_with_only_mandatory_fields, "AttributeTarget": "RSV"}
106-
model = IterationValidation(**data)
107-
assert model.attribute_target == "RSV"
108-
109-
def test_attribute_target_accepts_none(self, valid_iteration_rule_with_only_mandatory_fields):
110-
data = {**valid_iteration_rule_with_only_mandatory_fields, "AttributeTarget": None}
111-
model = IterationValidation(**data)
112-
assert model.attribute_target is None
113-
114-
# RuleStop
115-
def test_rule_stop_uses_default_when_missing(self, valid_iteration_rule_with_only_mandatory_fields):
116-
data = valid_iteration_rule_with_only_mandatory_fields.copy()
117-
data.pop("RuleStop", None)
118-
model = IterationValidation(**data)
119-
assert model.rule_stop == RuleStop(RULE_STOP_DEFAULT)
120-
121-
def test_rule_stop_accepts_value(self, valid_iteration_rule_with_only_mandatory_fields):
122-
data = {**valid_iteration_rule_with_only_mandatory_fields, "RuleStop": "soft_stop"}
123-
model = IterationValidation(**data)
124-
assert model.rule_stop == "soft_stop"
125-
126-
# CommsRouting
127-
def test_comms_routing_accepts_value(self, valid_iteration_rule_with_only_mandatory_fields):
128-
data = {**valid_iteration_rule_with_only_mandatory_fields, "CommsRouting": "RouteA"}
129-
model = IterationValidation(**data)
130-
assert model.comms_routing == "RouteA"
131-
132-
def test_comms_routing_accepts_none(self, valid_iteration_rule_with_only_mandatory_fields):
133-
data = {**valid_iteration_rule_with_only_mandatory_fields, "CommsRouting": None}
134-
model = IterationValidation(**data)
135-
assert model.comms_routing is None
127+
# AttributeName (Optional)
128+
@pytest.mark.parametrize("attr_name", ["status", "user_type", None])
129+
def test_valid_attribute_name(self, attr_name, valid_iteration_rule_with_only_mandatory_fields):
130+
data = valid_iteration_rule_with_only_mandatory_fields.copy()
131+
data["AttributeName"] = attr_name
132+
result = IterationRuleValidation(**data)
133+
assert result.attribute_name == attr_name
134+
135+
@pytest.mark.parametrize("attr_name", [123, {}, []])
136+
def test_invalid_attribute_name(self, attr_name, valid_iteration_rule_with_only_mandatory_fields):
137+
data = valid_iteration_rule_with_only_mandatory_fields.copy()
138+
data["AttributeName"] = attr_name
139+
with pytest.raises(ValidationError):
140+
IterationRuleValidation(**data)
141+
142+
# CohortLabel (Optional)
143+
@pytest.mark.parametrize("label", ["Cohort_A", "Segment_2025", None, ""])
144+
def test_valid_cohort_label(self, label, valid_iteration_rule_with_only_mandatory_fields):
145+
data = valid_iteration_rule_with_only_mandatory_fields.copy()
146+
data["CohortLabel"] = label
147+
result = IterationRuleValidation(**data)
148+
assert result.cohort_label == label
149+
150+
@pytest.mark.parametrize("label", [123, [], {}])
151+
def test_invalid_cohort_label(self, label, valid_iteration_rule_with_only_mandatory_fields):
152+
data = valid_iteration_rule_with_only_mandatory_fields.copy()
153+
data["CohortLabel"] = label
154+
with pytest.raises(ValidationError):
155+
IterationRuleValidation(**data)
156+
157+
# AttributeTarget (Optional)
158+
@pytest.mark.parametrize("target", ["target_value", None])
159+
def test_valid_attribute_target(self, target, valid_iteration_rule_with_only_mandatory_fields):
160+
data = valid_iteration_rule_with_only_mandatory_fields.copy()
161+
data["AttributeTarget"] = target
162+
result = IterationRuleValidation(**data)
163+
assert result.attribute_target == target
164+
165+
@pytest.mark.parametrize("target", [123, [], {}])
166+
def test_invalid_attribute_target(self, target, valid_iteration_rule_with_only_mandatory_fields):
167+
data = valid_iteration_rule_with_only_mandatory_fields.copy()
168+
data["AttributeTarget"] = target
169+
with pytest.raises(ValidationError):
170+
IterationRuleValidation(**data)
171+
172+
# RuleStop (Optional boolean with string "Y"/"N")
173+
@pytest.mark.parametrize("rule_stop_value", [True, False, "Y", "N", "YES", "NO", "YEAH", "ONE"])
174+
def test_valid_rule_stop(self, rule_stop_value, valid_iteration_rule_with_only_mandatory_fields):
175+
data = valid_iteration_rule_with_only_mandatory_fields.copy()
176+
data["RuleStop"] = rule_stop_value
177+
result = IterationRuleValidation(**data)
178+
assert isinstance(result.rule_stop, bool)
179+
180+
@pytest.mark.parametrize("rule_stop_value", [{}, None])
181+
def test_invalid_rule_stop(self, rule_stop_value, valid_iteration_rule_with_only_mandatory_fields):
182+
data = valid_iteration_rule_with_only_mandatory_fields.copy()
183+
data["RuleStop"] = rule_stop_value
184+
with pytest.raises(ValidationError):
185+
IterationRuleValidation(**data)
186+
187+
# CommsRouting (Optional)
188+
@pytest.mark.parametrize("routing_value", ["route_A", None])
189+
def test_valid_comms_routing(self, routing_value, valid_iteration_rule_with_only_mandatory_fields):
190+
data = valid_iteration_rule_with_only_mandatory_fields.copy()
191+
data["CommsRouting"] = routing_value
192+
result = IterationRuleValidation(**data)
193+
assert result.comms_routing == routing_value
194+
195+
@pytest.mark.parametrize("routing_value", [123, [], {}])
196+
def test_invalid_comms_routing(self, routing_value, valid_iteration_rule_with_only_mandatory_fields):
197+
data = valid_iteration_rule_with_only_mandatory_fields.copy()
198+
data["CommsRouting"] = routing_value
199+
with pytest.raises(ValidationError):
200+
IterationRuleValidation(**data)
201+
202+
203+
class TestBUCValidations:
204+
@pytest.mark.parametrize(
205+
"rule_stop_input, expected_bool",
206+
[
207+
(True, True),
208+
(False, False),
209+
("Y", True),
210+
("N", False),
211+
("YES", False),
212+
("NO", False),
213+
("YEAH", False),
214+
("ONE", False),
215+
],
216+
)
217+
def test_rule_stop_boolean_resolution(
218+
self, rule_stop_input, expected_bool, valid_iteration_rule_with_only_mandatory_fields
219+
):
220+
data = valid_iteration_rule_with_only_mandatory_fields.copy()
221+
data["RuleStop"] = rule_stop_input
222+
result = IterationRuleValidation(**data)
223+
assert result.rule_stop is expected_bool

0 commit comments

Comments
 (0)