test_cleanup_contract.py 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. import json
  2. import re
  3. import unittest
  4. from pathlib import Path
  5. ROOT = Path(__file__).resolve().parents[1]
  6. def read(path: str) -> str:
  7. return (ROOT / path).read_text(encoding="utf-8")
  8. def active_route_source() -> str:
  9. lines = read("frontend/src/router/routes.js").splitlines()
  10. return "\n".join(line for line in lines if not line.lstrip().startswith("//"))
  11. class CleanupContractTest(unittest.TestCase):
  12. def test_retained_frontend_capabilities_exist(self):
  13. retained = [
  14. "frontend/src/views/home/index.vue",
  15. "frontend/src/views/home/edit.vue",
  16. "frontend/src/views/home/workbench.js",
  17. "frontend/src/views/knowledgeBaseProduct/index.vue",
  18. "frontend/src/views/dataGovernance/dataSecurity/index.vue",
  19. "frontend/src/views/dataGovernance/dataProcess/index.vue",
  20. "frontend/src/views/dataFactory/workflow/index.vue",
  21. "frontend/src/views/dataService/dataOrder/index.vue",
  22. "frontend/src/views/dataService/dataProduct/index.vue",
  23. "frontend/src/views/dataReview/index.vue",
  24. "frontend/src/views/systemManage/error/404.vue",
  25. ]
  26. for path in retained:
  27. with self.subTest(path=path):
  28. self.assertTrue((ROOT / path).is_file(), path)
  29. routes = active_route_source()
  30. for component in [
  31. "dataGovernance/dataSecurity",
  32. "dataGovernance/dataProcess",
  33. "dataFactory/workflow",
  34. "dataService/dataOrder",
  35. "dataService/dataProduct",
  36. "dataReview",
  37. ]:
  38. with self.subTest(component=component):
  39. self.assertIn(component, routes)
  40. def test_confirmed_legacy_frontend_directories_are_removed(self):
  41. removed = [
  42. "frontend/src/views/dataChart",
  43. "frontend/src/views/modelSystem",
  44. "frontend/src/views/dataAsset",
  45. "frontend/src/views/dataDiagram",
  46. "frontend/src/views/questionnaireInquiry",
  47. "frontend/src/views/knowledgeBaseResume",
  48. "frontend/src/views/dataGovernance/dataResource",
  49. "frontend/src/views/dataGovernance/dataModules",
  50. "frontend/src/views/dataGovernance/dataIndicator",
  51. "frontend/src/views/dataBook/dataResource",
  52. "frontend/src/views/dataBook/dataModel",
  53. "frontend/src/views/dataBook/indicator",
  54. "frontend/src/views/dataFactory/dispatch",
  55. "frontend/src/views/dataFactory/logManage",
  56. "frontend/src/views/dataFactory/nodeManage",
  57. "frontend/src/views/dataFactory/productionLineMonitor",
  58. "frontend/src/components/ChartTemplate/humanResource",
  59. "frontend/src/components/phoneVerify",
  60. "frontend/src/components/UnifyExport",
  61. "frontend/src/views/login/components/forget.vue",
  62. "frontend/src/views/login/components/register.vue",
  63. ]
  64. for path in removed:
  65. with self.subTest(path=path):
  66. self.assertFalse((ROOT / path).exists(), path)
  67. def test_confirmed_legacy_routes_are_removed(self):
  68. source = read("frontend/src/router/routes.js")
  69. removed_tokens = [
  70. "/data-chart",
  71. "dataAsset",
  72. "/model-system",
  73. "dataGovernance/dataResource",
  74. "dataGovernance/dataModules",
  75. "dataGovernance/dataIndicator",
  76. "dataBook/dataResource",
  77. "dataBook/dataModel",
  78. "dataBook/indicator",
  79. ]
  80. for token in removed_tokens:
  81. with self.subTest(token=token):
  82. self.assertNotIn(token, source)
  83. def test_frontend_api_surface_is_slimmed(self):
  84. for path in [
  85. "frontend/src/api/dataChart.js",
  86. "frontend/src/api/chartCustomized.js",
  87. "frontend/src/api/report.js",
  88. "frontend/src/api/productionLine.js",
  89. "frontend/src/api/dataBook.js",
  90. "frontend/src/api/system.js",
  91. "frontend/src/api/menu.js",
  92. ]:
  93. with self.subTest(path=path):
  94. self.assertFalse((ROOT / path).exists(), path)
  95. data_factory = read("frontend/src/api/dataFactory.js")
  96. exports = set(re.findall(r"^export function (\w+)", data_factory, re.MULTILINE))
  97. self.assertEqual(
  98. exports,
  99. {
  100. "getWorkflows",
  101. "getWorkflow",
  102. "getWorkflowStatus",
  103. "activateWorkflow",
  104. "deactivateWorkflow",
  105. "getWorkflowExecutions",
  106. "getAllExecutions",
  107. "getExecution",
  108. "triggerWorkflow",
  109. "healthCheck",
  110. },
  111. )
  112. governance = read("frontend/src/api/dataGovernance.js")
  113. for token in ["const dataResource", "const dataModel", "const dataIndicator"]:
  114. self.assertNotIn(token, governance)
  115. for token in ["runDataFlow", "getDataFlowExecute", "getDataFlowLog"]:
  116. self.assertNotIn(token, governance)
  117. data_origin = read("frontend/src/api/dataOrigin.js")
  118. self.assertNotIn("businessCard", data_origin)
  119. self.assertIn("getDatasourceList", data_origin)
  120. user_api = read("frontend/src/api/user.js")
  121. self.assertEqual(
  122. set(re.findall(r"^export function (\w+)", user_api, re.MULTILINE)),
  123. {
  124. "login",
  125. "getCurrentUser",
  126. "listIdentityProviders",
  127. "beginEnterpriseLogin",
  128. "exchangeIdentityCode",
  129. "refreshIdentitySession",
  130. "logoutIdentitySession",
  131. },
  132. )
  133. workbench = read("frontend/src/views/home/workbench.js")
  134. for widget_id in [
  135. "pending-review",
  136. "order-status",
  137. "product-statistics",
  138. "datasource-health",
  139. "n8n-execution-status",
  140. ]:
  141. self.assertIn(widget_id, workbench)
  142. def test_backend_runtime_and_obsolete_subsystems_are_removed(self):
  143. routes = read("app/api/data_flow/routes.py")
  144. service = read("app/core/data_flow/dataflows.py")
  145. for token in [
  146. "execute-dataflow",
  147. "get-dataflow-status",
  148. "get-dataflow-logs",
  149. ]:
  150. self.assertNotIn(token, routes)
  151. for token in [
  152. "def execute_dataflow(",
  153. "def get_dataflow_status(",
  154. "def get_dataflow_logs(",
  155. ]:
  156. self.assertNotIn(token, service)
  157. self.assertFalse((ROOT / "mcp-servers/task-manager").exists())
  158. self.assertNotIn("AIRFLOW_", read("app/config/config.py"))
  159. self.assertNotIn("AIRFLOW_", read("deployment/dataops.env"))
  160. self.assertNotIn("/auth/register", read("app/api/system/routes.py"))
  161. removed_sql = [
  162. "create_calendar_info.sql",
  163. "create_calendar_records.sql",
  164. "create_wechat_users.sql",
  165. "create_duplicate_business_cards_table.sql",
  166. "hotel_group_brands_ddl.sql",
  167. "hotel_positions_ddl.sql",
  168. ]
  169. for filename in removed_sql:
  170. self.assertFalse((ROOT / "database" / filename).exists(), filename)
  171. def test_n8n_and_dataflow_definition_contracts_remain(self):
  172. factory_routes = read("app/api/data_factory/routes.py")
  173. for token in ["/workflows", "/executions", "/health"]:
  174. self.assertIn(token, factory_routes)
  175. flow_routes = read("app/api/data_flow/routes.py")
  176. for token in [
  177. "/get-dataflows-list",
  178. "/get-dataflow/<int:dataflow_id>",
  179. "/add-dataflow",
  180. "/update-dataflow/<int:dataflow_id>",
  181. "/delete-dataflow/<int:dataflow_id>",
  182. "/get-BD-list",
  183. "/get-script/<int:dataflow_id>",
  184. ]:
  185. self.assertIn(token, flow_routes)
  186. def test_hopms_acceptance_assets_remain(self):
  187. retained = [
  188. "scripts/import_hopms_dataset.py",
  189. "tests/test_hopms_import.py",
  190. "docs/HOPMs标准数据集-V1.1.3.docx",
  191. "docs/generated/hopms_dry_run.json",
  192. "docs/generated/hopms_import_result.json",
  193. ]
  194. for path in retained:
  195. with self.subTest(path=path):
  196. self.assertTrue((ROOT / path).is_file(), path)
  197. def test_frontend_targets_supported_node_lts(self):
  198. package = json.loads(read("frontend/package.json"))
  199. engine = package["engines"]["node"]
  200. self.assertTrue(engine.startswith(">=24") or engine.startswith("24"), engine)
  201. if __name__ == "__main__":
  202. unittest.main()