From db8c5659cb54cbfd0ac1e59888059d45b4fe4d3d Mon Sep 17 00:00:00 2001 From: Paul Buetow Date: Tue, 26 May 2026 10:52:01 +0300 Subject: feat(askcli): add projects subcommand --- internal/askcli/command_projects_test.go | 144 +++++++++++++++++++++++++++++++ 1 file changed, 144 insertions(+) create mode 100644 internal/askcli/command_projects_test.go (limited to 'internal/askcli/command_projects_test.go') diff --git a/internal/askcli/command_projects_test.go b/internal/askcli/command_projects_test.go new file mode 100644 index 0000000..3059afb --- /dev/null +++ b/internal/askcli/command_projects_test.go @@ -0,0 +1,144 @@ +package askcli + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "io" + "strings" + "testing" +) + +func TestHandleProjects_ListsUniqueProjects(t *testing.T) { + oldFind := projectsFindTaskBinary + oldRun := projectsRunTaskCommand + t.Cleanup(func() { + projectsFindTaskBinary = oldFind + projectsRunTaskCommand = oldRun + }) + + projectsFindTaskBinary = func() (string, error) { return "task", nil } + projectsRunTaskCommand = func(ctx context.Context, name string, args []string, stdin io.Reader, stdout, stderr io.Writer) error { + tasks := []TaskExport{ + {UUID: "1", Project: "hexai", Status: "pending", Urgency: 1}, + {UUID: "2", Project: "dtail", Status: "pending", Urgency: 2, Start: "2026-01-01T00:00:00Z"}, + {UUID: "3", Project: "hexai", Status: "pending", Urgency: 3}, + {UUID: "4", Project: "", Status: "pending", Urgency: 4}, + } + _, _ = io.WriteString(stdout, taskExportJSON(tasks)) + return nil + } + + ctx := context.Background() + d := NewDispatcher(nil) + var stdout, stderr bytes.Buffer + code, err := d.Dispatch(ctx, []string{"projects"}, nil, &stdout, &stderr) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if code != 0 { + t.Fatalf("unexpected exit code: %d", code) + } + + lines := strings.Split(strings.TrimSpace(stdout.String()), "\n") + if len(lines) != 1 || lines[0] != "hexai" { + t.Fatalf("expected [hexai], got %q", lines) + } +} + +func TestHandleProjects_JSONOutput(t *testing.T) { + oldFind := projectsFindTaskBinary + oldRun := projectsRunTaskCommand + t.Cleanup(func() { + projectsFindTaskBinary = oldFind + projectsRunTaskCommand = oldRun + }) + + projectsFindTaskBinary = func() (string, error) { return "task", nil } + projectsRunTaskCommand = func(ctx context.Context, name string, args []string, stdin io.Reader, stdout, stderr io.Writer) error { + tasks := []TaskExport{ + {UUID: "1", Project: "hexai", Status: "pending", Urgency: 1}, + {UUID: "2", Project: "dtail", Status: "pending", Urgency: 2}, + } + _, _ = io.WriteString(stdout, taskExportJSON(tasks)) + return nil + } + + ctx := context.Background() + d := NewDispatcher(nil) + var stdout, stderr bytes.Buffer + code, err := d.Dispatch(ctx, []string{"--json", "projects"}, nil, &stdout, &stderr) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if code != 0 { + t.Fatalf("unexpected exit code: %d", code) + } + + if !strings.Contains(stdout.String(), `"dtail"`) || !strings.Contains(stdout.String(), `"hexai"`) { + t.Fatalf("unexpected JSON output: %s", stdout.String()) + } +} + +func TestHandleProjects_EmptyResult(t *testing.T) { + oldFind := projectsFindTaskBinary + oldRun := projectsRunTaskCommand + t.Cleanup(func() { + projectsFindTaskBinary = oldFind + projectsRunTaskCommand = oldRun + }) + + projectsFindTaskBinary = func() (string, error) { return "task", nil } + projectsRunTaskCommand = func(ctx context.Context, name string, args []string, stdin io.Reader, stdout, stderr io.Writer) error { + _, _ = io.WriteString(stdout, "[]") + return nil + } + + ctx := context.Background() + d := NewDispatcher(nil) + var stdout, stderr bytes.Buffer + code, err := d.Dispatch(ctx, []string{"projects"}, nil, &stdout, &stderr) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if code != 0 { + t.Fatalf("unexpected exit code: %d", code) + } + if stdout.String() != "" { + t.Fatalf("expected no output, got %q", stdout.String()) + } +} + +func TestHandleProjects_ForwardsTaskExportError(t *testing.T) { + oldFind := projectsFindTaskBinary + oldRun := projectsRunTaskCommand + t.Cleanup(func() { + projectsFindTaskBinary = oldFind + projectsRunTaskCommand = oldRun + }) + + projectsFindTaskBinary = func() (string, error) { return "task", nil } + projectsRunTaskCommand = func(ctx context.Context, name string, args []string, stdin io.Reader, stdout, stderr io.Writer) error { + return fmt.Errorf("some error") + } + + ctx := context.Background() + d := NewDispatcher(nil) + var stdout, stderr bytes.Buffer + code, err := d.Dispatch(ctx, []string{"projects"}, nil, &stdout, &stderr) + if err == nil { + t.Fatal("expected error") + } + if code != 1 { + t.Fatalf("expected exit code 1, got %d", code) + } +} + +func taskExportJSON(tasks []TaskExport) string { + data, err := json.Marshal(tasks) + if err != nil { + panic(err) + } + return string(data) +} -- cgit v1.2.3