Skip to content

Commit 9da3e01

Browse files
test(spp_change_request_v2): improve coverage for dynamic approval methods
Add 12 tests covering previously uncovered branches in change_request.py: - _normalize_value_for_cel: char, date, boolean, integer, many2many, falsy boolean/integer, None without record, hierarchical parent - _compute_field_values_for_cel: no field selected - _resolve_dynamic_approval: no selected field - _check_can_submit: dynamic CR without field selection
1 parent d9b12ec commit 9da3e01

File tree

1 file changed

+135
-0
lines changed

1 file changed

+135
-0
lines changed

spp_change_request_v2/tests/test_dynamic_approval.py

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -922,3 +922,138 @@ def test_normalize_value_includes_code_for_vocabulary(self):
922922

923923
# Restore registrant
924924
self.registrant.write({"gender_id": False})
925+
926+
# ──────────────────────────────────────────────────────────────────────────
927+
# TEST 17 – _normalize_value_for_cel covers all field types
928+
# ──────────────────────────────────────────────────────────────────────────
929+
930+
def test_normalize_value_char_field(self):
931+
"""_normalize_value_for_cel returns string for char/text/selection fields."""
932+
cr = self._create_cr()
933+
detail = cr.get_detail()
934+
# given_name is a Char field on the detail model
935+
result = cr._normalize_value_for_cel("hello", detail, "given_name")
936+
self.assertEqual(result, "hello")
937+
938+
def test_normalize_value_date_field(self):
939+
"""_normalize_value_for_cel passes through date values."""
940+
cr = self._create_cr()
941+
detail = cr.get_detail()
942+
# birthdate is a Date field on the detail model
943+
from datetime import date
944+
945+
test_date = date(2000, 1, 15)
946+
result = cr._normalize_value_for_cel(test_date, detail, "birthdate")
947+
self.assertEqual(result, test_date)
948+
949+
def test_normalize_value_falsy_boolean_returns_false(self):
950+
"""_normalize_value_for_cel returns False (not None) for falsy boolean fields."""
951+
cr = self._create_cr()
952+
# Use a known boolean field from the detail base model
953+
detail = cr.get_detail()
954+
result = cr._normalize_value_for_cel(False, detail, "is_applied")
955+
self.assertIs(result, False, "Falsy boolean must return False, not None.")
956+
957+
def test_normalize_value_falsy_integer_returns_zero(self):
958+
"""_normalize_value_for_cel returns 0 for falsy integer/float/monetary fields."""
959+
cr = self._create_cr()
960+
registrant = cr.registrant_id
961+
# res.partner has 'color' as an Integer field
962+
result = cr._normalize_value_for_cel(False, registrant, "color")
963+
self.assertEqual(result, 0, "Falsy integer must return 0, not None.")
964+
965+
def test_normalize_value_truthy_boolean(self):
966+
"""_normalize_value_for_cel returns bool for boolean fields."""
967+
cr = self._create_cr()
968+
detail = cr.get_detail()
969+
result = cr._normalize_value_for_cel(True, detail, "is_applied")
970+
self.assertIs(result, True)
971+
972+
def test_normalize_value_truthy_integer(self):
973+
"""_normalize_value_for_cel returns numeric value for integer fields."""
974+
cr = self._create_cr()
975+
registrant = cr.registrant_id
976+
result = cr._normalize_value_for_cel(42, registrant, "color")
977+
self.assertEqual(result, 42)
978+
979+
def test_normalize_value_many2many_field(self):
980+
"""_normalize_value_for_cel returns dict with ids and count for x2many fields."""
981+
cr = self._create_cr()
982+
registrant = cr.registrant_id
983+
# category_id is a Many2many field on res.partner
984+
result = cr._normalize_value_for_cel(registrant.category_id, registrant, "category_id")
985+
self.assertIsInstance(result, dict)
986+
self.assertIn("ids", result)
987+
self.assertIn("count", result)
988+
self.assertIsInstance(result["ids"], list)
989+
990+
def test_normalize_value_none_without_record(self):
991+
"""_normalize_value_for_cel returns None when record is None."""
992+
cr = self._create_cr()
993+
result = cr._normalize_value_for_cel(None, None, None)
994+
self.assertIsNone(result)
995+
996+
# ──────────────────────────────────────────────────────────────────────────
997+
# TEST 18 – _compute_field_values_for_cel with no field selected
998+
# ──────────────────────────────────────────────────────────────────────────
999+
1000+
def test_compute_field_values_no_field_selected(self):
1001+
"""_compute_field_values_for_cel returns None values when no field is selected."""
1002+
cr = self._create_cr()
1003+
# Don't set field_to_modify — selected_field_name stays empty
1004+
result = cr._compute_field_values_for_cel()
1005+
self.assertIsNone(result["old_value"])
1006+
self.assertIsNone(result["new_value"])
1007+
1008+
# ──────────────────────────────────────────────────────────────────────────
1009+
# TEST 19 – _resolve_dynamic_approval with no selected field
1010+
# ──────────────────────────────────────────────────────────────────────────
1011+
1012+
def test_resolve_dynamic_approval_no_field_returns_none(self):
1013+
"""_resolve_dynamic_approval returns None when selected_field_name is not set."""
1014+
cr = self._create_cr()
1015+
result = cr._resolve_dynamic_approval()
1016+
self.assertIsNone(result, "Must return None when no field is selected.")
1017+
1018+
# ──────────────────────────────────────────────────────────────────────────
1019+
# TEST 20 – _check_can_submit validates dynamic field selection
1020+
# ──────────────────────────────────────────────────────────────────────────
1021+
1022+
def test_check_can_submit_rejects_without_field_selection(self):
1023+
"""_check_can_submit raises ValidationError for dynamic CR without field selection."""
1024+
cr = self._create_cr()
1025+
# CR is dynamic but no field_to_modify set
1026+
with self.assertRaises(ValidationError):
1027+
cr._check_can_submit()
1028+
1029+
# ──────────────────────────────────────────────────────────────────────────
1030+
# TEST 21 – Many2one normalization with hierarchical parent
1031+
# ──────────────────────────────────────────────────────────────────────────
1032+
1033+
def test_normalize_many2one_with_parent(self):
1034+
"""_normalize_value_for_cel includes parent dict for hierarchical records."""
1035+
# Find a vocabulary code with a parent, or create one
1036+
VocabCode = self.env["spp.vocabulary.code"]
1037+
parent = VocabCode.search([("parent_id", "!=", False)], limit=1)
1038+
if not parent:
1039+
# Try to find any vocab code and check if the model supports parent
1040+
any_code = VocabCode.search([], limit=1)
1041+
if not any_code or "parent_id" not in any_code._fields:
1042+
self.skipTest("Need hierarchical vocabulary codes with parent_id.")
1043+
# Create parent-child pair
1044+
vocab = any_code.vocabulary_id
1045+
parent_rec = VocabCode.create({"name": "Test Parent", "code": "TEST_PARENT", "vocabulary_id": vocab.id})
1046+
child_rec = VocabCode.create(
1047+
{"name": "Test Child", "code": "TEST_CHILD", "vocabulary_id": vocab.id, "parent_id": parent_rec.id}
1048+
)
1049+
parent = child_rec
1050+
1051+
cr = self._create_cr()
1052+
detail = cr.get_detail()
1053+
normalized = cr._normalize_value_for_cel(parent, detail, "gender_id")
1054+
1055+
self.assertIsInstance(normalized, dict)
1056+
self.assertIn("parent", normalized, "Hierarchical vocab must include parent dict.")
1057+
self.assertIn("id", normalized["parent"])
1058+
self.assertIn("name", normalized["parent"])
1059+
self.assertIn("code", normalized["parent"])

0 commit comments

Comments
 (0)