test: add inbox command integration coverage

This commit is contained in:
2026-03-19 11:48:15 +08:00
parent 5f59350577
commit eb52a0e770
17 changed files with 2366 additions and 76 deletions
@@ -0,0 +1,187 @@
package inbox
import "testing"
func TestFetchReturnsPendingThreadForTargetAgent(t *testing.T) {
t.Parallel()
dbPath := initCommandTestDB(t)
sendPendingThread(t, dbPath, "leader", "worker-a", "Implement task", "Create API endpoint")
fetchOut := runInboxCommand(
t,
"--db", dbPath,
"--json",
"fetch",
"--agent", "worker-a",
"--status", "pending",
)
var fetchResp map[string]any
mustDecodeJSON(t, fetchOut, &fetchResp)
threads, ok := nestedValue(t, fetchResp, "data", "threads").([]any)
if !ok || len(threads) < 1 {
t.Fatalf("expected at least one fetched thread, got %#v", nestedValue(t, fetchResp, "data", "threads"))
}
thread, ok := threads[0].(map[string]any)
if !ok {
t.Fatalf("expected thread object, got %#v", threads[0])
}
if got, _ := thread["assigned_to"].(string); got != "worker-a" {
t.Fatalf("expected assigned_to worker-a, got %#v", thread["assigned_to"])
}
if got, _ := thread["status"].(string); got != "pending" {
t.Fatalf("expected pending status, got %#v", thread["status"])
}
}
func TestFetchRespectsStatusAndLimitFilters(t *testing.T) {
t.Parallel()
dbPath := initCommandTestDB(t)
sendPendingThread(t, dbPath, "leader", "worker-a", "Task A", "Pending task")
blockedThreadID := sendPendingThread(t, dbPath, "leader", "worker-a", "Task B", "Blocked task")
runInboxCommand(
t,
"--db", dbPath,
"--json",
"claim",
"--agent", "worker-a",
"--thread", blockedThreadID,
)
runInboxCommand(
t,
"--db", dbPath,
"--json",
"update",
"--agent", "worker-a",
"--thread", blockedThreadID,
"--status", "blocked",
"--summary", "Need decision",
"--payload-json", `{"question":"continue?"}`,
)
fetchOut := runInboxCommand(
t,
"--db", dbPath,
"--json",
"fetch",
"--agent", "worker-a",
"--status", "pending,blocked",
"--limit", "1",
)
var fetchResp map[string]any
mustDecodeJSON(t, fetchOut, &fetchResp)
threads, ok := nestedValue(t, fetchResp, "data", "threads").([]any)
if !ok {
t.Fatalf("expected threads array, got %#v", nestedValue(t, fetchResp, "data", "threads"))
}
if len(threads) > 1 {
t.Fatalf("expected at most one thread with limit=1, got %d", len(threads))
}
if len(threads) == 0 {
t.Fatalf("expected one thread with status filter, got empty result")
}
thread, ok := threads[0].(map[string]any)
if !ok {
t.Fatalf("expected thread object, got %#v", threads[0])
}
status, _ := thread["status"].(string)
if status != "pending" && status != "blocked" {
t.Fatalf("expected pending or blocked status, got %#v", thread["status"])
}
}
func TestFetchUnreadUsesReadCursor(t *testing.T) {
t.Parallel()
dbPath := initCommandTestDB(t)
threadID := sendPendingThread(t, dbPath, "leader", "worker-e", "Review navbar copy", "Check top nav wording")
firstFetchOut := runInboxCommand(
t,
"--db", dbPath,
"--json",
"fetch",
"--agent", "worker-e",
"--status", "pending",
"--unread",
)
var firstFetchResp map[string]any
mustDecodeJSON(t, firstFetchOut, &firstFetchResp)
firstThreads, ok := nestedValue(t, firstFetchResp, "data", "threads").([]any)
if !ok || len(firstThreads) != 1 {
t.Fatalf("expected one unread thread before mark-read, got %#v", nestedValue(t, firstFetchResp, "data", "threads"))
}
runInboxCommand(
t,
"--db", dbPath,
"--agent", "worker-e",
"--json",
"show",
"--thread", threadID,
"--mark-read",
)
stdout, _, exitCode := executeInboxCommand(
"--db", dbPath,
"--json",
"fetch",
"--agent", "worker-e",
"--status", "pending",
"--unread",
)
if exitCode != 10 {
t.Fatalf("expected unread fetch to return no_matching_work after mark-read, got exit=%d stdout=%s", exitCode, stdout)
}
assertErrorJSON(t, stdout, "no_matching_work")
runInboxCommand(
t,
"--db", dbPath,
"--json",
"send",
"--from", "leader",
"--to", "worker-e",
"--thread", threadID,
"--summary", "Use sentence case",
"--body", "Keep the nav labels in sentence case.",
)
thirdFetchOut := runInboxCommand(
t,
"--db", dbPath,
"--json",
"fetch",
"--agent", "worker-e",
"--status", "pending",
"--unread",
)
var thirdFetchResp map[string]any
mustDecodeJSON(t, thirdFetchOut, &thirdFetchResp)
thirdThreads, ok := nestedValue(t, thirdFetchResp, "data", "threads").([]any)
if !ok || len(thirdThreads) != 1 {
t.Fatalf("expected unread thread to reappear after new message, got %#v", nestedValue(t, thirdFetchResp, "data", "threads"))
}
}
func TestFetchReturnsNoMatchingWorkWhenEmpty(t *testing.T) {
t.Parallel()
dbPath := initCommandTestDB(t)
stdout, _, exitCode := executeInboxCommand(
"--db", dbPath,
"--json",
"fetch",
"--agent", "worker-z",
"--status", "pending",
)
if exitCode != 10 {
t.Fatalf("expected exit code 10, got %d", exitCode)
}
assertErrorJSON(t, stdout, "no_matching_work")
}