Files
dingtalk-workspace-cli/test/cli_compat/todo_test.go
T
ybc❤️zyrand猷诺 426810a776 fix(todo): correct tool name from query_todo_detail to get_todo_detail (#202)
The todo task get command was calling query_todo_detail which returns
empty results. Changed to get_todo_detail to match the tool name
defined in discovery.json, restoring correct behavior.

Co-authored-by: 猷诺 <bicheng.ybc@alibaba-inc.com>
2026-04-29 22:59:37 +08:00

322 lines
9.7 KiB
Go

package cli_compat_test
import (
"testing"
)
// ── task create ─────────────────────────────────────────────
func TestTodoTaskCreate_should_call_create_personal_todo(t *testing.T) {
cap := setupTestDeps(t, "todo")
root := buildRoot()
err := execCmd(t, root, []string{"todo", "task", "create"}, map[string]string{
"title": "修复线上Bug",
"executors": "userId1,userId2",
})
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
assertToolName(t, cap, "create_personal_todo")
}
func TestTodoTaskCreate_should_pass_subject_and_executorIds(t *testing.T) {
cap := setupTestDeps(t, "todo")
root := buildRoot()
_ = execCmd(t, root, []string{"todo", "task", "create"}, map[string]string{
"title": "提交报告",
"executors": "userId1",
})
assertToolArg(t, cap, "PersonalTodoCreateVO", map[string]any{
"subject": "提交报告",
"executorIds": []any{"userId1"},
})
}
func TestTodoTaskCreate_should_pass_priority(t *testing.T) {
cap := setupTestDeps(t, "todo")
root := buildRoot()
_ = execCmd(t, root, []string{"todo", "task", "create"}, map[string]string{
"title": "紧急任务",
"executors": "userId1",
"priority": "40",
})
last := cap.last()
if last == nil {
t.Fatal("no MCP call captured")
}
vo, ok := last.Args["PersonalTodoCreateVO"].(map[string]any)
if !ok {
t.Fatalf("expected PersonalTodoCreateVO map, got %T", last.Args["PersonalTodoCreateVO"])
}
if vo["priority"] != float64(40) {
t.Errorf("expected priority=40, got %v", vo["priority"])
}
}
func TestTodoTaskCreate_should_error_when_title_missing(t *testing.T) {
_ = setupTestDeps(t, "todo")
root := buildRoot()
err := execCmd(t, root, []string{"todo", "task", "create"}, map[string]string{
"executors": "userId1",
})
if err == nil {
t.Fatal("expected error when --title is missing")
}
}
func TestTodoTaskCreate_should_error_when_executors_missing(t *testing.T) {
_ = setupTestDeps(t, "todo")
root := buildRoot()
err := execCmd(t, root, []string{"todo", "task", "create"}, map[string]string{
"title": "测试待办",
})
if err == nil {
t.Fatal("expected error when --executors is missing")
}
}
func TestTodoTaskCreate_should_accept_subject_alias(t *testing.T) {
cap := setupTestDeps(t, "todo")
root := buildRoot()
err := execCmd(t, root, []string{"todo", "task", "create"}, map[string]string{
"subject": "通过别名创建",
"executors": "userId1",
})
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
assertToolName(t, cap, "create_personal_todo")
}
func TestTodoTaskCreate_should_not_call_mcp_in_dry_run(t *testing.T) {
cap := setupTestDepsWithDryRun(t, "todo")
root := buildRoot()
_ = execCmd(t, root, []string{"todo", "task", "create"}, map[string]string{
"title": "Dry Run",
"executors": "userId1",
})
assertCallCount(t, cap, 0)
}
// ── task list ───────────────────────────────────────────────
func TestTodoTaskList_should_call_get_user_todos(t *testing.T) {
cap := setupTestDeps(t, "todo")
root := buildRoot()
err := execCmd(t, root, []string{"todo", "task", "list"}, nil)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
assertToolName(t, cap, "get_user_todos_in_current_org")
}
func TestTodoTaskList_should_pass_status_filter(t *testing.T) {
cap := setupTestDeps(t, "todo")
root := buildRoot()
_ = execCmd(t, root, []string{"todo", "task", "list"}, map[string]string{
"status": "false",
})
assertToolArg(t, cap, "isDone", "false")
assertToolArg(t, cap, "todoStatus", "false")
}
// ── task update ─────────────────────────────────────────────
func TestTodoTaskUpdate_should_call_update_todo_task(t *testing.T) {
cap := setupTestDeps(t, "todo")
root := buildRoot()
err := execCmd(t, root, []string{"todo", "task", "update"}, map[string]string{
"task-id": "TASK_001",
"title": "新标题",
})
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
assertToolName(t, cap, "update_todo_task")
}
func TestTodoTaskUpdate_should_pass_TodoUpdateRequest(t *testing.T) {
cap := setupTestDeps(t, "todo")
root := buildRoot()
_ = execCmd(t, root, []string{"todo", "task", "update"}, map[string]string{
"task-id": "TASK_001",
"title": "更新标题",
})
last := cap.last()
if last == nil {
t.Fatal("no MCP call captured")
}
req, ok := last.Args["TodoUpdateRequest"].(map[string]any)
if !ok {
t.Fatalf("expected TodoUpdateRequest map, got %T", last.Args["TodoUpdateRequest"])
}
if req["taskId"] != "TASK_001" {
t.Errorf("expected taskId=TASK_001, got %v", req["taskId"])
}
if req["subject"] != "更新标题" {
t.Errorf("expected subject=更新标题, got %v", req["subject"])
}
}
func TestTodoTaskUpdate_should_pass_done_flag(t *testing.T) {
cap := setupTestDeps(t, "todo")
root := buildRoot()
_ = execCmd(t, root, []string{"todo", "task", "update"}, map[string]string{
"task-id": "TASK_001",
"done": "true",
})
last := cap.last()
if last == nil {
t.Fatal("no MCP call captured")
}
req, ok := last.Args["TodoUpdateRequest"].(map[string]any)
if !ok {
t.Fatalf("expected TodoUpdateRequest map, got %T", last.Args["TodoUpdateRequest"])
}
if req["isDone"] != true {
t.Errorf("expected isDone=true, got %v", req["isDone"])
}
}
func TestTodoTaskUpdate_should_error_when_task_id_missing(t *testing.T) {
_ = setupTestDeps(t, "todo")
root := buildRoot()
err := execCmd(t, root, []string{"todo", "task", "update"}, map[string]string{
"title": "新标题",
})
if err == nil {
t.Fatal("expected error when --task-id is missing")
}
}
func TestTodoTaskUpdate_should_not_call_mcp_in_dry_run(t *testing.T) {
cap := setupTestDepsWithDryRun(t, "todo")
root := buildRoot()
_ = execCmd(t, root, []string{"todo", "task", "update"}, map[string]string{
"task-id": "TASK_001",
"title": "Dry Run",
})
assertCallCount(t, cap, 0)
}
// ── task done ───────────────────────────────────────────────
func TestTodoTaskDone_should_call_update_todo_done_status(t *testing.T) {
cap := setupTestDeps(t, "todo")
root := buildRoot()
err := execCmd(t, root, []string{"todo", "task", "done"}, map[string]string{
"task-id": "TASK_001",
"status": "true",
})
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
assertToolName(t, cap, "update_todo_done_status")
}
func TestTodoTaskDone_should_pass_taskId_and_isDone(t *testing.T) {
cap := setupTestDeps(t, "todo")
root := buildRoot()
_ = execCmd(t, root, []string{"todo", "task", "done"}, map[string]string{
"task-id": "TASK_001",
"status": "true",
})
assertToolArg(t, cap, "taskId", "TASK_001")
assertToolArg(t, cap, "isDone", "true")
}
func TestTodoTaskDone_should_error_when_task_id_missing(t *testing.T) {
_ = setupTestDeps(t, "todo")
root := buildRoot()
err := execCmd(t, root, []string{"todo", "task", "done"}, map[string]string{
"status": "true",
})
if err == nil {
t.Fatal("expected error when --task-id is missing")
}
}
func TestTodoTaskDone_should_error_when_status_missing(t *testing.T) {
_ = setupTestDeps(t, "todo")
root := buildRoot()
err := execCmd(t, root, []string{"todo", "task", "done"}, map[string]string{
"task-id": "TASK_001",
})
if err == nil {
t.Fatal("expected error when --status is missing")
}
}
// ── task get ────────────────────────────────────────────────
func TestTodoTaskGet_should_call_query_todo_detail(t *testing.T) {
cap := setupTestDeps(t, "todo")
root := buildRoot()
err := execCmd(t, root, []string{"todo", "task", "get"}, map[string]string{
"task-id": "TASK_001",
})
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
assertToolName(t, cap, "get_todo_detail")
}
func TestTodoTaskGet_should_pass_taskId(t *testing.T) {
cap := setupTestDeps(t, "todo")
root := buildRoot()
_ = execCmd(t, root, []string{"todo", "task", "get"}, map[string]string{
"task-id": "TASK_002",
})
assertToolArg(t, cap, "taskId", "TASK_002")
}
func TestTodoTaskGet_should_error_when_task_id_missing(t *testing.T) {
_ = setupTestDeps(t, "todo")
root := buildRoot()
err := execCmd(t, root, []string{"todo", "task", "get"}, nil)
if err == nil {
t.Fatal("expected error when --task-id is missing")
}
}
// ── task delete ─────────────────────────────────────────────
func TestTodoTaskDelete_should_call_delete_todo(t *testing.T) {
cap := setupTestDepsAutoConfirm(t, "todo")
root := buildRoot()
err := execCmd(t, root, []string{"todo", "task", "delete"}, map[string]string{
"task-id": "TASK_DEL",
})
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
assertToolName(t, cap, "delete_todo")
}
func TestTodoTaskDelete_should_pass_taskId(t *testing.T) {
cap := setupTestDepsAutoConfirm(t, "todo")
root := buildRoot()
_ = execCmd(t, root, []string{"todo", "task", "delete"}, map[string]string{
"task-id": "TASK_DEL",
})
assertToolArg(t, cap, "taskId", "TASK_DEL")
}
func TestTodoTaskDelete_should_error_when_task_id_missing(t *testing.T) {
_ = setupTestDeps(t, "todo")
root := buildRoot()
err := execCmd(t, root, []string{"todo", "task", "delete"}, nil)
if err == nil {
t.Fatal("expected error when --task-id is missing")
}
}
func TestTodoTaskDelete_should_not_call_mcp_in_dry_run(t *testing.T) {
cap := setupTestDepsWithDryRun(t, "todo")
root := buildRoot()
_ = execCmd(t, root, []string{"todo", "task", "delete"}, map[string]string{
"task-id": "TASK_001",
})
assertCallCount(t, cap, 0)
}