test_oa_assignee.py 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. """OA 审批人解析单元测试"""
  2. import unittest
  3. from unittest.mock import MagicMock, patch
  4. from app.services.oa_assignee import AssigneeResolveError, resolve_assignees
  5. class TestOaAssignee(unittest.TestCase):
  6. def test_users_resolves_active_ids(self):
  7. db = MagicMock()
  8. with patch(
  9. "app.services.oa_assignee._active_user_id",
  10. side_effect=lambda _db, uid, _tn: uid if uid else None,
  11. ):
  12. users, meta = resolve_assignees(
  13. db,
  14. tenant_no="zkxw",
  15. assignee_config={"assigneeType": "users", "userIds": ["u1", "u1", ""]},
  16. initiator_user_id="initiator",
  17. )
  18. self.assertEqual(users, ["u1"])
  19. self.assertEqual(meta.get("resolve_source"), "users")
  20. def test_dept_leader_resolves_by_initiator_dept(self):
  21. db = MagicMock()
  22. dept = MagicMock(leader_user_id="leaderA")
  23. db.query.return_value.filter.return_value.first.return_value = dept
  24. with patch(
  25. "app.services.oa_assignee._active_user_id",
  26. side_effect=lambda _db, uid, _tn: uid if uid else None,
  27. ):
  28. users, meta = resolve_assignees(
  29. db,
  30. tenant_no="zkxw",
  31. assignee_config={"assigneeType": "dept_leader"},
  32. initiator_user_id="zhang",
  33. initiator_dept_id="deptA",
  34. )
  35. self.assertEqual(users, ["leaderA"])
  36. self.assertEqual(meta.get("resolve_source"), "dept_leader")
  37. def test_direct_supervisor_fallback_to_dept_leader(self):
  38. db = MagicMock()
  39. initiator = MagicMock(supervisor_user_id=None, dept_id="deptA")
  40. dept = MagicMock(leader_user_id="leaderA")
  41. db.query.return_value.filter.return_value.first.side_effect = [initiator, dept]
  42. with patch(
  43. "app.services.oa_assignee._active_user_id",
  44. side_effect=lambda _db, uid, _tn: uid if uid else None,
  45. ):
  46. users, meta = resolve_assignees(
  47. db,
  48. tenant_no="zkxw",
  49. assignee_config={"assigneeType": "direct_supervisor"},
  50. initiator_user_id="no_supervisor",
  51. initiator_dept_id="deptA",
  52. advanced={"supervisorFallbackToDeptLeader": True},
  53. )
  54. self.assertEqual(users, ["leaderA"])
  55. self.assertEqual(meta.get("resolve_source"), "supervisor_fallback_dept_leader")
  56. def test_direct_supervisor_no_fallback_raises(self):
  57. db = MagicMock()
  58. initiator = MagicMock(supervisor_user_id=None, dept_id="deptA")
  59. db.query.return_value.filter.return_value.first.return_value = initiator
  60. with patch(
  61. "app.services.oa_assignee._active_user_id",
  62. return_value=None,
  63. ):
  64. with self.assertRaises(AssigneeResolveError):
  65. resolve_assignees(
  66. db,
  67. tenant_no="zkxw",
  68. assignee_config={"assigneeType": "direct_supervisor"},
  69. initiator_user_id="no_supervisor",
  70. initiator_dept_id="deptA",
  71. advanced={"supervisorFallbackToDeptLeader": False},
  72. )
  73. def test_oa_role_gm(self):
  74. db = MagicMock()
  75. with patch(
  76. "app.services.oa_assignee.oa_crud.list_oa_role_user_ids",
  77. return_value=["gm_user", "inactive"],
  78. ), patch(
  79. "app.services.oa_assignee._active_user_id",
  80. side_effect=lambda _db, uid, _tn: uid if uid == "gm_user" else None,
  81. ):
  82. users, meta = resolve_assignees(
  83. db,
  84. tenant_no="zkxw",
  85. assignee_config={"assigneeType": "oa_roles", "oaRoleIds": ["gm_role_id"]},
  86. initiator_user_id="zhang",
  87. )
  88. self.assertEqual(users, ["gm_user"])
  89. self.assertEqual(meta.get("resolve_source"), "oa_roles")
  90. def test_never_reads_sys_role(self):
  91. db = MagicMock()
  92. with patch(
  93. "app.services.oa_assignee.oa_crud.list_oa_role_user_ids",
  94. return_value=["oa_only"],
  95. ) as mock_list, patch(
  96. "app.services.oa_assignee._active_user_id",
  97. side_effect=lambda _db, uid, _tn: uid,
  98. ):
  99. users, _meta = resolve_assignees(
  100. db,
  101. tenant_no="zkxw",
  102. assignee_config={"assigneeType": "oa_roles", "oaRoleIds": ["r1"]},
  103. initiator_user_id="zhang",
  104. )
  105. self.assertEqual(users, ["oa_only"])
  106. mock_list.assert_called_once()
  107. # 业务路径不得查询 sys_role
  108. for call in db.query.call_args_list:
  109. args = call[0] if call[0] else ()
  110. for a in args:
  111. name = getattr(a, "__name__", None) or getattr(a, "__tablename__", None) or str(a)
  112. self.assertNotIn("SysRole", str(name))
  113. self.assertNotIn("sys_role", str(name))
  114. def test_initiator_select_empty_raises(self):
  115. db = MagicMock()
  116. with self.assertRaises(AssigneeResolveError):
  117. resolve_assignees(
  118. db,
  119. tenant_no="zkxw",
  120. assignee_config={"assigneeType": "initiator_select"},
  121. initiator_user_id="zhang",
  122. initiator_select_user_ids=[],
  123. )
  124. if __name__ == "__main__":
  125. unittest.main()