| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247 |
- """OA 发布校验单元测试"""
- import unittest
- from unittest.mock import MagicMock, patch
- from app.services.oa_publish import (
- count_fillable_fields,
- validate_control_types,
- validate_draft_for_publish,
- validate_flow_tree,
- )
- def _linear_ok_flow():
- return {
- "id": "s1",
- "type": "start",
- "name": "发起人",
- "child": {
- "id": "a1",
- "type": "approval",
- "name": "部门负责人",
- "approverConfig": {"assigneeType": "dept_leader"},
- "child": {"id": "e1", "type": "end", "name": "结束"},
- },
- }
- def _condition_flow(rules=None, when=None, is_default=False):
- return {
- "type": "start",
- "name": "发起人",
- "child": {
- "type": "condition",
- "name": "条件",
- "conditionGroups": [
- {
- "name": "分支1",
- "rules": rules if rules is not None else [],
- "when": when,
- "isDefault": False,
- "child": {
- "type": "approval",
- "name": "审批A",
- "approverConfig": {"assigneeType": "dept_leader"},
- "child": {"type": "end", "name": "结束"},
- },
- },
- {
- "name": "默认",
- "rules": [],
- "isDefault": True,
- "child": {
- "type": "approval",
- "name": "审批B",
- "approverConfig": {"assigneeType": "dept_leader"},
- "child": {"type": "end", "name": "结束"},
- },
- },
- ],
- },
- }
- class TestOaPublishValidate(unittest.TestCase):
- def test_count_fillable_fields(self):
- schema = {
- "rule": [
- {"type": "html", "props": {"innerHTML": "说明"}},
- {"type": "input", "field": "title", "title": "标题"},
- {
- "type": "fcRow",
- "children": [
- {"type": "inputNumber", "field": "days", "title": "天数"},
- ],
- },
- ]
- }
- self.assertEqual(count_fillable_fields(schema), 2)
- self.assertEqual(count_fillable_fields({"rule": []}), 0)
- def test_flow_ok(self):
- self.assertEqual(validate_flow_tree(_linear_ok_flow()), [])
- def test_flow_missing_end(self):
- tree = {
- "type": "start",
- "name": "发起人",
- "child": {
- "type": "approval",
- "name": "审批",
- "approverConfig": {"assigneeType": "users", "userIds": ["u1"]},
- },
- }
- errs = validate_flow_tree(tree)
- self.assertTrue(any("结束" in e or "后续" in e for e in errs))
- def test_approval_users_empty_rejected(self):
- tree = {
- "type": "start",
- "child": {
- "type": "approval",
- "name": "审批",
- "approverConfig": {"assigneeType": "users", "userIds": []},
- "child": {"type": "end"},
- },
- }
- errs = validate_flow_tree(tree)
- self.assertTrue(any("指定成员" in e for e in errs))
- def test_condition_branch_incomplete(self):
- tree = {
- "type": "start",
- "child": {
- "type": "condition",
- "name": "条件",
- "conditionGroups": [{"name": "大于3天", "rules": [], "child": None}],
- },
- }
- errs = validate_flow_tree(tree)
- self.assertTrue(any("下游" in e or "结束" in e for e in errs))
- def test_draft_requires_fillable_and_assignee(self):
- db = MagicMock()
- with patch(
- "app.services.oa_publish.validate_oa_roles_referenced",
- return_value=[],
- ):
- errs = validate_draft_for_publish(
- db,
- tenant_no="zkxw",
- form_schema={"rule": [{"type": "html"}]},
- flow_tree={
- "type": "start",
- "child": {
- "type": "approval",
- "approverConfig": {"assigneeType": "users", "userIds": []},
- "child": {"type": "end"},
- },
- },
- )
- self.assertTrue(any("可填字段" in e for e in errs))
- self.assertTrue(any("指定成员" in e for e in errs))
- def test_valid_draft_passes_form_and_flow(self):
- db = MagicMock()
- with patch(
- "app.services.oa_publish.validate_oa_roles_referenced",
- return_value=[],
- ):
- errs = validate_draft_for_publish(
- db,
- tenant_no="zkxw",
- form_schema={"rule": [{"type": "input", "field": "reason"}]},
- flow_tree=_linear_ok_flow(),
- )
- self.assertEqual(errs, [])
- def test_unknown_control_type_rejected(self):
- errs = validate_control_types(
- {"rule": [{"type": "aiMagicBox", "field": "x"}, {"type": "input", "field": "y"}]}
- )
- self.assertTrue(any("aiMagicBox" in e for e in errs))
- def test_upload_is_allowed(self):
- self.assertEqual(
- validate_control_types(
- {"rule": [{"type": "upload", "field": "files", "title": "上传"}]}
- ),
- [],
- )
- self.assertEqual(
- count_fillable_fields(
- {"rule": [{"type": "upload", "field": "files", "title": "上传"}]}
- ),
- 1,
- )
- class TestConditionPublish(unittest.TestCase):
- def test_when_only_rejected(self):
- errs = validate_flow_tree(_condition_flow(rules=[], when="{days} > 3"))
- self.assertTrue(any("可视化" in e or "重新配置" in e or "rules" in e for e in errs))
- def test_rules_empty_non_default_rejected(self):
- errs = validate_flow_tree(_condition_flow(rules=[]))
- self.assertTrue(any("条件" in e for e in errs))
- def test_rules_ok(self):
- errs = validate_flow_tree(
- _condition_flow(rules=[{"field": "days", "op": ">", "value": 3}])
- )
- self.assertEqual(errs, [])
- def test_invalid_field_reference(self):
- db = MagicMock()
- with patch(
- "app.services.oa_publish.validate_oa_roles_referenced",
- return_value=[],
- ):
- errs = validate_draft_for_publish(
- db,
- tenant_no="zkxw",
- form_schema={
- "rule": [
- {
- "type": "inputNumber",
- "field": "days",
- "title": "天数",
- "useInCondition": True,
- "$required": True,
- }
- ]
- },
- flow_tree=_condition_flow(
- rules=[{"field": "other", "op": ">", "value": 1}]
- ),
- )
- self.assertTrue(any("无效字段" in e or "other" in e for e in errs))
- def test_field_not_flagged_rejected(self):
- db = MagicMock()
- with patch(
- "app.services.oa_publish.validate_oa_roles_referenced",
- return_value=[],
- ):
- errs = validate_draft_for_publish(
- db,
- tenant_no="zkxw",
- form_schema={
- "rule": [
- {
- "type": "inputNumber",
- "field": "days",
- "title": "天数",
- "useInCondition": False,
- }
- ]
- },
- flow_tree=_condition_flow(
- rules=[{"field": "days", "op": ">", "value": 3}]
- ),
- )
- self.assertTrue(any("无效字段" in e or "参与" in e for e in errs))
- if __name__ == "__main__":
- unittest.main()
|