From df5832f41bbbfb4c8703b9a2e0f0b00a116a90cc Mon Sep 17 00:00:00 2001 From: lanrtop Date: Sat, 3 Oct 2026 06:34:06 +0900 Subject: [PATCH] =?UTF-8?q?fix(delivery/mcp):=20=E8=A1=A5=20get=5Fdelivery?= =?UTF-8?q?=5Fstatus=20=E7=BB=8F=20scoped=20dispatch=20=E8=BD=AC=E5=8F=91?= =?UTF-8?q?=20pr=5Fnumber/branch=20=E7=9A=84=E5=9B=9E=E5=BD=92=E6=B5=8B?= =?UTF-8?q?=E8=AF=95=EF=BC=88P3-F=20=E5=AE=A1=E6=9F=A5=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 使者回传 #203 的症状是「传 pr_number 也不起作用」,但原有 MCP 层测试只覆盖非法参数报错, dispatch 若丢弃已解析的查询目标、改传默认值,全部测试仍通过。新增 scoped dispatch 正向测试, 断言 pr_number/branch/null 分别得到 pull_request/branch/local_branch 目标;已用变异 (dispatch 改传 DeliveryQuery::default())确认该测试会失败。 Co-Authored-By: Claude Opus 5.5 --- src-tauri/src/mcp_tools.rs | 61 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/src-tauri/src/mcp_tools.rs b/src-tauri/src/mcp_tools.rs index d0c0ae1..853e2ae 100644 --- a/src-tauri/src/mcp_tools.rs +++ b/src-tauri/src/mcp_tools.rs @@ -2680,6 +2680,67 @@ mod tests { assert!(text.contains("feat/delivery-status-by-pr"), "{text}"); } + /// 使者回传 #203 的症状正是「传 pr_number 也不起作用」:经 scoped dispatch 断言 + /// pr_number/branch 真正到达能力本体(未绑定 Gitea,不发网络请求)。 + #[tokio::test] + async fn delivery_status_dispatch_forwards_pr_and_branch_targets() { + db::init_test_pool(); + let base = temp_base("delivery_target_dispatch"); + { + let conn = db::pool().get().unwrap(); + conn.execute( + "INSERT OR IGNORE INTO project_profiles (id, name) VALUES ('delivery-target-profile', 'Delivery target fixture')", + [], + ) + .unwrap(); + conn.execute( + "INSERT OR IGNORE INTO project_workspaces (id, profile_id, win_path) VALUES ('delivery-target', 'delivery-target-profile', ?1)", + [base.to_str().unwrap()], + ) + .unwrap(); + } + let target_of = |result: &Value| { + assert_ne!(result["isError"], true, "{result}"); + result["structuredContent"]["target"].clone() + }; + + let by_pr = tools_call_for_project( + Some(&json!({"name": "get_delivery_status", "arguments": { + "pr_number": 31, "branch": "feat/worktree" + }})), + "delivery-target", + ) + .await; + let target = target_of(&by_pr); + assert_eq!(target["mode"], "pull_request", "{by_pr}"); + assert_eq!(target["pr_number"], 31, "{by_pr}"); + assert_eq!( + by_pr["structuredContent"]["pull_request"]["state"], + "not_configured" + ); + + let by_branch = tools_call_for_project( + Some(&json!({"name": "get_delivery_status", "arguments": { + "branch": "feat/worktree" + }})), + "delivery-target", + ) + .await; + let target = target_of(&by_branch); + assert_eq!(target["mode"], "branch", "{by_branch}"); + assert_eq!(target["branch"], "feat/worktree", "{by_branch}"); + + let default = tools_call_for_project( + Some(&json!({"name": "get_delivery_status", "arguments": { + "pr_number": null, "branch": null + }})), + "delivery-target", + ) + .await; + assert_eq!(target_of(&default)["mode"], "local_branch", "{default}"); + let _ = std::fs::remove_dir_all(&base); + } + #[tokio::test] async fn delivery_status_tool_requires_project_id() { let result = tools_call(Some(&json!({