Files
ai-workflow-skill/internal/cli/inbox/list_integration_test.go
T

184 lines
4.9 KiB
Go

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")
}