summaryrefslogtreecommitdiff
path: root/internal/askcli/dispatch_test.go
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-03-27 07:24:47 +0200
committerPaul Buetow <paul@buetow.org>2026-03-27 07:24:47 +0200
commitc4354f1985089366d673a89664d7428337d0e56c (patch)
treeb2cb725648eb75d544aec65dbcf67124ab478943 /internal/askcli/dispatch_test.go
parenta9d00ab5e5b4ff3d08f71f24f00d6b3bc4579d02 (diff)
Fix dispatcher routing test for 38d5bd83-29e7-4a3c-ad44-21dddfbdfe22
Diffstat (limited to 'internal/askcli/dispatch_test.go')
-rw-r--r--internal/askcli/dispatch_test.go200
1 files changed, 162 insertions, 38 deletions
diff --git a/internal/askcli/dispatch_test.go b/internal/askcli/dispatch_test.go
index 48c3e55..a863481 100644
--- a/internal/askcli/dispatch_test.go
+++ b/internal/askcli/dispatch_test.go
@@ -5,8 +5,11 @@ import (
"context"
"io"
"os"
+ "path/filepath"
+ "reflect"
"strings"
"testing"
+ "time"
)
func TestDispatcher_Help(t *testing.T) {
@@ -152,46 +155,167 @@ func TestDispatcher_DispatchPersistsJSONFlagOnDispatcher(t *testing.T) {
}
func TestDispatcher_AllSubcommandsReachExecutor(t *testing.T) {
- subcommands := []string{}
- subcommandArgs := map[string][]string{
- "delete": {"delete", "test-uuid"},
- "denotate": {"denotate", "test-uuid", "text"},
- "modify": {"modify", "test-uuid", "priority:H"},
- "annotate": {"annotate", "test-uuid", "note"},
- "start": {"start", "test-uuid"},
- "stop": {"stop", "test-uuid"},
- "done": {"done", "test-uuid"},
- "priority": {"priority", "test-uuid", "H"},
- "tag": {"tag", "test-uuid", "+cli"},
- "dep": {"dep", "list", "test-uuid"},
- "list": {"list"},
- "all": {"all"},
- "ready": {"ready"},
- "urgency": {"urgency"},
- "info": {"info", "test-uuid"},
- "add": {"add", "new task description"},
- }
- for _, sub := range subcommands {
- var stdout, stderr bytes.Buffer
- calls := 0
- d := NewDispatcher(&spyRunner{runFn: func(ctx context.Context, args []string, stdin io.Reader, stdout_, stderr_ io.Writer) (int, error) {
- calls++
- if args[0] == "export" || args[0] == "uuid" {
- io.WriteString(stdout_, `[{"uuid":"test-uuid","description":"Test","status":"pending","priority":"M","tags":[],"urgency":10,"depends":[]}]`)
+ dir := t.TempDir()
+ oldRoot := taskAliasCacheRoot
+ oldNow := nowTaskAliasCache
+ taskAliasCacheRoot = func() (string, error) { return filepath.Join(dir, "hexai"), nil }
+ nowTaskAliasCache = func() time.Time { return time.Date(2026, 3, 27, 12, 0, 0, 0, time.UTC) }
+ defer func() {
+ taskAliasCacheRoot = oldRoot
+ nowTaskAliasCache = oldNow
+ }()
+
+ taskJSONFor := func(uuid string) string {
+ return `[{"uuid":"` + uuid + `","description":"Test","status":"pending","priority":"M","tags":[],"urgency":10,"depends":[]}]`
+ }
+
+ cases := []struct {
+ name string
+ args []string
+ wantCalls [][]string
+ }{
+ {
+ name: "list",
+ args: []string{"list"},
+ wantCalls: [][]string{{"status:pending", "export"}},
+ },
+ {
+ name: "all",
+ args: []string{"all"},
+ wantCalls: [][]string{{"export"}},
+ },
+ {
+ name: "ready",
+ args: []string{"ready"},
+ wantCalls: [][]string{{"+READY", "export"}},
+ },
+ {
+ name: "urgency",
+ args: []string{"urgency"},
+ wantCalls: [][]string{{"export"}},
+ },
+ {
+ name: "complete-uuids",
+ args: []string{"complete-uuids"},
+ wantCalls: [][]string{{"status:pending", "export"}},
+ },
+ {
+ name: "info",
+ args: []string{"info", "test-uuid"},
+ wantCalls: [][]string{{"uuid:test-uuid", "export"}},
+ },
+ {
+ name: "add",
+ args: []string{"add", "new task description"},
+ wantCalls: [][]string{{"add", "rc.verbose=nothing", "rc.verbose=new-uuid", "new task description"}},
+ },
+ {
+ name: "annotate",
+ args: []string{"annotate", "test-uuid", "note"},
+ wantCalls: [][]string{{"uuid:test-uuid", "export"}, {"uuid:test-uuid", "annotate", "note"}},
+ },
+ {
+ name: "start",
+ args: []string{"start", "test-uuid"},
+ wantCalls: [][]string{{"uuid:test-uuid", "export"}, {"uuid:test-uuid", "start"}},
+ },
+ {
+ name: "stop",
+ args: []string{"stop", "test-uuid"},
+ wantCalls: [][]string{{"uuid:test-uuid", "export"}, {"uuid:test-uuid", "stop"}},
+ },
+ {
+ name: "done",
+ args: []string{"done", "test-uuid"},
+ wantCalls: [][]string{{"uuid:test-uuid", "export"}, {"uuid:test-uuid", "done"}},
+ },
+ {
+ name: "priority",
+ args: []string{"priority", "test-uuid", "H"},
+ wantCalls: [][]string{{"uuid:test-uuid", "export"}, {"uuid:test-uuid", "modify", "priority:H"}},
+ },
+ {
+ name: "tag",
+ args: []string{"tag", "test-uuid", "+cli"},
+ wantCalls: [][]string{{"uuid:test-uuid", "export"}, {"uuid:test-uuid", "modify", "+cli"}},
+ },
+ {
+ name: "modify",
+ args: []string{"modify", "test-uuid", "priority:H"},
+ wantCalls: [][]string{{"uuid:test-uuid", "export"}, {"uuid:test-uuid", "modify", "priority:H"}},
+ },
+ {
+ name: "denotate",
+ args: []string{"denotate", "test-uuid", "text"},
+ wantCalls: [][]string{{"uuid:test-uuid", "export"}, {"uuid:test-uuid", "denotate", "text"}},
+ },
+ {
+ name: "delete",
+ args: []string{"delete", "test-uuid"},
+ wantCalls: [][]string{{"uuid:test-uuid", "export"}, {"uuid:test-uuid", "delete"}},
+ },
+ {
+ name: "dep list",
+ args: []string{"dep", "list", "test-uuid"},
+ wantCalls: [][]string{{"uuid:test-uuid", "export"}},
+ },
+ {
+ name: "dep add",
+ args: []string{"dep", "add", "test-uuid", "dep-uuid"},
+ wantCalls: [][]string{{"uuid:test-uuid", "export"}, {"uuid:dep-uuid", "export"}, {"uuid:test-uuid", "modify", "depends:dep-uuid"}},
+ },
+ {
+ name: "dep rm",
+ args: []string{"dep", "rm", "test-uuid", "dep-uuid"},
+ wantCalls: [][]string{{"uuid:test-uuid", "export"}, {"uuid:dep-uuid", "export"}, {"uuid:test-uuid", "modify", "depends:-dep-uuid"}},
+ },
+ }
+
+ for _, tc := range cases {
+ t.Run(tc.name, func(t *testing.T) {
+ var calls [][]string
+ d := NewDispatcher(&spyRunner{runFn: func(ctx context.Context, args []string, stdin io.Reader, stdout, stderr io.Writer) (int, error) {
+ calls = append(calls, append([]string(nil), args...))
+ switch strings.Join(args, " ") {
+ case "export", "status:pending export", "+READY export":
+ _, _ = io.WriteString(stdout, taskJSONFor("test-uuid"))
+ case "uuid:test-uuid export":
+ _, _ = io.WriteString(stdout, taskJSONFor("test-uuid"))
+ case "uuid:dep-uuid export":
+ _, _ = io.WriteString(stdout, taskJSONFor("dep-uuid"))
+ case "add rc.verbose=nothing rc.verbose=new-uuid new task description":
+ _, _ = io.WriteString(stdout, "Created task task-uuid-abc.\n")
+ case "uuid:test-uuid annotate note":
+ case "uuid:test-uuid start":
+ case "uuid:test-uuid stop":
+ case "uuid:test-uuid done":
+ case "uuid:test-uuid modify priority:H":
+ case "uuid:test-uuid modify +cli":
+ case "uuid:test-uuid modify depends:dep-uuid":
+ case "uuid:test-uuid modify depends:-dep-uuid":
+ case "uuid:test-uuid denotate text":
+ case "uuid:test-uuid delete":
+ default:
+ t.Fatalf("unexpected runner args: %v", args)
+ }
+ return 0, nil
+ }})
+
+ var stdout, stderr bytes.Buffer
+ code, err := d.Dispatch(context.Background(), tc.args, nil, &stdout, &stderr)
+ if err != nil {
+ t.Fatalf("Dispatch returned error: %v", err)
}
- if args[0] == "add" {
- io.WriteString(stdout_, "Created task 123.\nUUID: test-uuid-abc")
+ if code != 0 {
+ t.Fatalf("Dispatch code = %d, want 0", code)
}
- return 0, nil
- }})
- args := []string{sub}
- if extra, ok := subcommandArgs[sub]; ok {
- args = extra
- }
- code, _ := d.Dispatch(context.Background(), args, nil, &stdout, &stderr)
- if code != 0 {
- t.Errorf("subcommand %q code = %d, want 0", sub, code)
- }
+ if !reflect.DeepEqual(calls, tc.wantCalls) {
+ t.Fatalf("runner calls = %#v, want %#v", calls, tc.wantCalls)
+ }
+ if stderr.Len() != 0 {
+ t.Fatalf("stderr = %q, want empty", stderr.String())
+ }
+ })
}
}