from uuid import uuid4 import pytest from pydantic import ValidationError from app.domain.schemas.operational_task import ( AgentArtifactsCommand, InvestigationDiagramNodeRef, InvestigationProgress, InvestigationReportInput, ) def test_waiting_and_unknown_node_states_survive_progress_and_final_report(): diagram = { "title": "等待系统结果", "mermaid": "flowchart LR\nDONE --> WAIT --> UNKNOWN --> UNSET", "node_refs": [ {"node_id": "DONE", "label": "查询完成", "status": "completed"}, {"node_id": "WAIT", "label": "等待系统结果", "status": "waiting"}, {"node_id": "UNKNOWN", "label": "未知", "status": None}, {"node_id": "UNSET", "label": "未确认"}, ], } progress = InvestigationProgress(summary="等待系统结果", diagram=diagram) report = InvestigationReportInput( title="报告", current_conclusion="已确认当前结果", conclusion_boundary="仅限查询范围", stage="final", outcome="concluded", data_gaps=[], diagram=diagram, ) assert report.diagram == progress.diagram assert [node.status for node in report.diagram.node_refs] == ["completed", "waiting", None, None] assert "status" not in report.diagram.node_refs[-1].model_fields_set def test_unknown_node_state_is_rejected(): with pytest.raises(ValidationError): InvestigationDiagramNodeRef(node_id="A", label="查询", status="blocked") def test_class_attached_nodes_are_valid_declarations_without_accepting_partial_ids(): payload = {"request_id": uuid4(), "source_session_id": "session-1", "progress": { "summary": "核查", "diagram": {"title": "路线", "mermaid": "flowchart TD\nQUERY:::running --> REVIEW:::pending", "node_refs": [{"node_id": "QUERY", "label": "核查", "status": "running"}, {"node_id": "REVIEW", "label": "复核", "status": "pending"}]}, }} assert AgentArtifactsCommand.model_validate(payload).progress.diagram.node_refs[0].status == "running" payload["progress"]["diagram"]["node_refs"][0]["node_id"] = "QUER" with pytest.raises(ValidationError, match="QUER"): AgentArtifactsCommand.model_validate(payload) @pytest.mark.parametrize("artifact", ["progress", "report"]) def test_artifact_write_rejects_node_refs_missing_from_mermaid(artifact): diagram = { "title": "当前路线", "mermaid": "flowchart TD\nA[绑定任务] --> B[核查证据]", "node_refs": [ {"node_id": "ctx", "label": "绑定任务", "status": "completed"}, {"node_id": "B", "label": "核查证据", "status": "running"}, ], } payload = ( {"summary": "正在核查", "diagram": diagram} if artifact == "progress" else { "title": "调查报告", "current_conclusion": "已确认当前范围", "conclusion_boundary": "仅限已核查资料", "stage": "final", "outcome": "concluded", "data_gaps": [], "diagram": diagram, } ) with pytest.raises(ValidationError, match="ctx"): AgentArtifactsCommand.model_validate({ "request_id": uuid4(), "source_session_id": "session-1", artifact: payload, }) def test_historical_progress_keeps_read_compatibility_for_undeclared_node_refs(): progress = InvestigationProgress.model_validate({ "summary": "旧进度", "diagram": { "title": "旧图", "mermaid": "flowchart TD\nA[绑定任务]", "node_refs": [{"node_id": "ctx", "label": "绑定任务", "status": "completed"}], }, }) assert progress.diagram.node_refs[0].node_id == "ctx"