test_cleanup_contract.py 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  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. {"login", "getCurrentUser"},
  124. )
  125. workbench = read("frontend/src/views/home/workbench.js")
  126. for widget_id in [
  127. "pending-review",
  128. "order-status",
  129. "product-statistics",
  130. "datasource-health",
  131. "n8n-execution-status",
  132. ]:
  133. self.assertIn(widget_id, workbench)
  134. def test_backend_runtime_and_obsolete_subsystems_are_removed(self):
  135. routes = read("app/api/data_flow/routes.py")
  136. service = read("app/core/data_flow/dataflows.py")
  137. for token in [
  138. "execute-dataflow",
  139. "get-dataflow-status",
  140. "get-dataflow-logs",
  141. ]:
  142. self.assertNotIn(token, routes)
  143. for token in [
  144. "def execute_dataflow(",
  145. "def get_dataflow_status(",
  146. "def get_dataflow_logs(",
  147. ]:
  148. self.assertNotIn(token, service)
  149. self.assertFalse((ROOT / "mcp-servers/task-manager").exists())
  150. self.assertNotIn("AIRFLOW_", read("app/config/config.py"))
  151. self.assertNotIn("AIRFLOW_", read("deployment/dataops.env"))
  152. self.assertNotIn("/auth/register", read("app/api/system/routes.py"))
  153. removed_sql = [
  154. "create_calendar_info.sql",
  155. "create_calendar_records.sql",
  156. "create_wechat_users.sql",
  157. "create_duplicate_business_cards_table.sql",
  158. "hotel_group_brands_ddl.sql",
  159. "hotel_positions_ddl.sql",
  160. ]
  161. for filename in removed_sql:
  162. self.assertFalse((ROOT / "database" / filename).exists(), filename)
  163. def test_n8n_and_dataflow_definition_contracts_remain(self):
  164. factory_routes = read("app/api/data_factory/routes.py")
  165. for token in ["/workflows", "/executions", "/health"]:
  166. self.assertIn(token, factory_routes)
  167. flow_routes = read("app/api/data_flow/routes.py")
  168. for token in [
  169. "/get-dataflows-list",
  170. "/get-dataflow/<int:dataflow_id>",
  171. "/add-dataflow",
  172. "/update-dataflow/<int:dataflow_id>",
  173. "/delete-dataflow/<int:dataflow_id>",
  174. "/get-BD-list",
  175. "/get-script/<int:dataflow_id>",
  176. ]:
  177. self.assertIn(token, flow_routes)
  178. def test_hopms_acceptance_assets_remain(self):
  179. retained = [
  180. "scripts/import_hopms_dataset.py",
  181. "tests/test_hopms_import.py",
  182. "docs/HOPMs标准数据集-V1.1.3.docx",
  183. "docs/generated/hopms_dry_run.json",
  184. "docs/generated/hopms_import_result.json",
  185. ]
  186. for path in retained:
  187. with self.subTest(path=path):
  188. self.assertTrue((ROOT / path).is_file(), path)
  189. def test_frontend_targets_supported_node_lts(self):
  190. package = json.loads(read("frontend/package.json"))
  191. engine = package["engines"]["node"]
  192. self.assertTrue(engine.startswith(">=24") or engine.startswith("24"), engine)
  193. if __name__ == "__main__":
  194. unittest.main()