test: add inbox command integration coverage
This commit is contained in:
@@ -0,0 +1,183 @@
|
||||
package inbox
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestListFiltersByStatus(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
dbPath := filepath.Join(t.TempDir(), "coord.db")
|
||||
runInboxCommand(t, "--db", dbPath, "--json", "init")
|
||||
|
||||
createThreadForList(t, dbPath, "leader", "worker-d", "Task pending", "Pending task")
|
||||
blockedThreadID := createThreadForList(t, dbPath, "leader", "worker-d", "Task blocked", "Blocked task")
|
||||
runInboxCommand(t, "--db", dbPath, "--json", "claim", "--agent", "worker-d", "--thread", blockedThreadID)
|
||||
runInboxCommand(
|
||||
t,
|
||||
"--db", dbPath,
|
||||
"--json",
|
||||
"update",
|
||||
"--agent", "worker-d",
|
||||
"--thread", blockedThreadID,
|
||||
"--status", "blocked",
|
||||
"--summary", "Need policy decision",
|
||||
)
|
||||
|
||||
listOut := runInboxCommand(
|
||||
t,
|
||||
"--db", dbPath,
|
||||
"--json",
|
||||
"list",
|
||||
"--agent", "worker-d",
|
||||
"--status", "pending,blocked",
|
||||
)
|
||||
|
||||
var listResp map[string]any
|
||||
mustDecodeJSON(t, listOut, &listResp)
|
||||
threads, ok := nestedValue(t, listResp, "data", "threads").([]any)
|
||||
if !ok || len(threads) < 2 {
|
||||
t.Fatalf("expected at least two matching threads, got %#v", nestedValue(t, listResp, "data", "threads"))
|
||||
}
|
||||
for _, raw := range threads {
|
||||
thread, ok := raw.(map[string]any)
|
||||
if !ok {
|
||||
t.Fatalf("expected thread object, got %#v", raw)
|
||||
}
|
||||
status, _ := thread["status"].(string)
|
||||
if status != "pending" && status != "blocked" {
|
||||
t.Fatalf("expected status pending or blocked, got %#v", status)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestListFiltersByCreatedBy(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
dbPath := filepath.Join(t.TempDir(), "coord.db")
|
||||
runInboxCommand(t, "--db", dbPath, "--json", "init")
|
||||
|
||||
createThreadForList(t, dbPath, "leader", "worker-d", "Leader task", "From leader")
|
||||
createThreadForList(t, dbPath, "planner", "worker-d", "Planner task", "From planner")
|
||||
|
||||
listOut := runInboxCommand(
|
||||
t,
|
||||
"--db", dbPath,
|
||||
"--json",
|
||||
"list",
|
||||
"--created-by", "leader",
|
||||
"--assigned-to", "worker-d",
|
||||
)
|
||||
|
||||
var listResp map[string]any
|
||||
mustDecodeJSON(t, listOut, &listResp)
|
||||
threads, ok := nestedValue(t, listResp, "data", "threads").([]any)
|
||||
if !ok || len(threads) == 0 {
|
||||
t.Fatalf("expected matching leader-created threads, got %#v", nestedValue(t, listResp, "data", "threads"))
|
||||
}
|
||||
for _, raw := range threads {
|
||||
thread, ok := raw.(map[string]any)
|
||||
if !ok {
|
||||
t.Fatalf("expected thread object, got %#v", raw)
|
||||
}
|
||||
if got := thread["created_by"]; got != "leader" {
|
||||
t.Fatalf("expected created_by leader, got %#v", got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestListFiltersByAssignedTo(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
dbPath := filepath.Join(t.TempDir(), "coord.db")
|
||||
runInboxCommand(t, "--db", dbPath, "--json", "init")
|
||||
|
||||
createThreadForList(t, dbPath, "leader", "worker-d", "Worker D task", "For worker-d")
|
||||
createThreadForList(t, dbPath, "leader", "worker-e", "Worker E task", "For worker-e")
|
||||
|
||||
listOut := runInboxCommand(
|
||||
t,
|
||||
"--db", dbPath,
|
||||
"--json",
|
||||
"list",
|
||||
"--assigned-to", "worker-d",
|
||||
"--status", "pending",
|
||||
)
|
||||
|
||||
var listResp map[string]any
|
||||
mustDecodeJSON(t, listOut, &listResp)
|
||||
threads, ok := nestedValue(t, listResp, "data", "threads").([]any)
|
||||
if !ok || len(threads) == 0 {
|
||||
t.Fatalf("expected assigned-to match, got %#v", nestedValue(t, listResp, "data", "threads"))
|
||||
}
|
||||
for _, raw := range threads {
|
||||
thread, ok := raw.(map[string]any)
|
||||
if !ok {
|
||||
t.Fatalf("expected thread object, got %#v", raw)
|
||||
}
|
||||
if got := thread["assigned_to"]; got != "worker-d" {
|
||||
t.Fatalf("expected assigned_to worker-d, got %#v", got)
|
||||
}
|
||||
if got := thread["status"]; got != "pending" {
|
||||
t.Fatalf("expected pending status, got %#v", got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestListRespectsLimit(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
dbPath := filepath.Join(t.TempDir(), "coord.db")
|
||||
runInboxCommand(t, "--db", dbPath, "--json", "init")
|
||||
|
||||
createThreadForList(t, dbPath, "leader", "worker-d", "Task 1", "Earlier task")
|
||||
time.Sleep(20 * time.Millisecond)
|
||||
createThreadForList(t, dbPath, "leader", "worker-d", "Task 2", "Latest task")
|
||||
|
||||
listOut := runInboxCommand(
|
||||
t,
|
||||
"--db", dbPath,
|
||||
"--json",
|
||||
"list",
|
||||
"--assigned-to", "worker-d",
|
||||
"--limit", "1",
|
||||
)
|
||||
|
||||
var listResp map[string]any
|
||||
mustDecodeJSON(t, listOut, &listResp)
|
||||
threads, ok := nestedValue(t, listResp, "data", "threads").([]any)
|
||||
if !ok {
|
||||
t.Fatalf("expected threads array, got %#v", nestedValue(t, listResp, "data", "threads"))
|
||||
}
|
||||
if len(threads) != 1 {
|
||||
t.Fatalf("expected exactly one row for limit=1, got %d", len(threads))
|
||||
}
|
||||
thread, ok := threads[0].(map[string]any)
|
||||
if !ok {
|
||||
t.Fatalf("expected thread object, got %#v", threads[0])
|
||||
}
|
||||
if got := thread["subject"]; got != "Task 2" {
|
||||
t.Fatalf("expected latest thread subject Task 2, got %#v", got)
|
||||
}
|
||||
}
|
||||
|
||||
func createThreadForList(t *testing.T, dbPath, from, to, subject, summary string) string {
|
||||
t.Helper()
|
||||
|
||||
sendOut := runInboxCommand(
|
||||
t,
|
||||
"--db", dbPath,
|
||||
"--json",
|
||||
"send",
|
||||
"--from", from,
|
||||
"--to", to,
|
||||
"--subject", subject,
|
||||
"--summary", summary,
|
||||
)
|
||||
var sendResp map[string]any
|
||||
mustDecodeJSON(t, sendOut, &sendResp)
|
||||
return nestedString(t, sendResp, "data", "thread", "thread_id")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user