package cmd import ( "bytes" "os" "path/filepath" "strings" "testing" "time" "github.com/warrenronsiek/ctask/internal/workspace" ) // callPath invokes runPath with stdout captured. func callPath(t *testing.T, root, query string) (string, error) { t.Helper() prevRoot := os.Getenv("CTASK_ROOT") os.Setenv("CTASK_ROOT", root) defer func() { if prevRoot == "" { os.Unsetenv("CTASK_ROOT") } else { os.Setenv("CTASK_ROOT", prevRoot) } }() r, w, _ := os.Pipe() prevStdout := os.Stdout os.Stdout = w defer func() { os.Stdout = prevStdout }() err := runPath(pathCmd, []string{query}) w.Close() var buf bytes.Buffer buf.ReadFrom(r) return buf.String(), err } func TestPathPrintsAbsolutePath(t *testing.T) { root := t.TempDir() dirName := "2026-04-22_path-active" wsDir := filepath.Join(root, "general", dirName) os.MkdirAll(wsDir, 0755) now := time.Now().UTC().Truncate(time.Second) meta := &workspace.TaskMeta{ ID: "t", Slug: "path-active", Title: "path-active", CreatedAt: now, UpdatedAt: now, Status: "active", Category: "general", Type: "task", Mode: "local", Agent: workspace.AgentSpec{Type: "claude"}, } workspace.WriteMeta(filepath.Join(wsDir, "task.yaml"), meta) out, err := callPath(t, root, "path-active") if err != nil { t.Fatalf("path: %v", err) } got := strings.TrimRight(out, "\r\n") want, _ := filepath.Abs(wsDir) if got != want { t.Errorf("output path mismatch:\nwant: %q\ngot: %q", want, got) } if !strings.HasSuffix(out, "\n") { t.Errorf("output should end with a newline, got: %q", out) } if filepath.IsAbs(got) != true { t.Errorf("output must be absolute, got: %q", got) } } func TestPathWorksOnArchivedWorkspace(t *testing.T) { root := t.TempDir() dirName := "2026-04-22_path-archived" wsDir := filepath.Join(root, "general", dirName) os.MkdirAll(wsDir, 0755) now := time.Now().UTC().Truncate(time.Second) meta := &workspace.TaskMeta{ ID: "t", Slug: "path-archived", Title: "path-archived", CreatedAt: now, UpdatedAt: now, ArchivedAt: &now, Status: "archived", Category: "general", Type: "task", Mode: "local", Agent: workspace.AgentSpec{Type: "claude"}, } workspace.WriteMeta(filepath.Join(wsDir, "task.yaml"), meta) out, err := callPath(t, root, "path-archived") if err != nil { t.Fatalf("path should find archived workspace: %v", err) } got := strings.TrimRight(out, "\r\n") want, _ := filepath.Abs(wsDir) if got != want { t.Errorf("output path mismatch:\nwant: %q\ngot: %q", want, got) } }