From dee37364c1c690207cb12c399f65e2b53537b5a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20B=C3=BCtow?= <1224732+snonux@users.noreply.github.com> Date: Thu, 19 Jun 2025 23:43:20 +0300 Subject: Add Taskwarrior CLI tests --- internal/task/task.go | 61 ++++++++++++++++++++++++++++++++++++++++++++++ internal/task/task_test.go | 56 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 117 insertions(+) create mode 100644 internal/task/task.go create mode 100644 internal/task/task_test.go (limited to 'internal/task') diff --git a/internal/task/task.go b/internal/task/task.go new file mode 100644 index 0000000..dcb3e9a --- /dev/null +++ b/internal/task/task.go @@ -0,0 +1,61 @@ +package task + +import ( + "bufio" + "bytes" + "encoding/json" + "os/exec" +) + +// Task represents a taskwarrior task as returned by `task export`. +type Task struct { + ID int `json:"id"` + UUID string `json:"uuid"` + Description string `json:"description"` + Tags []string `json:"tags"` + Status string `json:"status"` +} + +// Add creates a new task with the given description and tags. +func Add(description string, tags []string) error { + args := []string{"add"} + for _, t := range tags { + if len(t) > 0 && t[0] != '+' { + t = "+" + t + } + args = append(args, t) + } + args = append(args, description) + + cmd := exec.Command("task", args...) + return cmd.Run() +} + +// Export retrieves all tasks using `task export rc.json.array=off` and parses +// the JSON output into a slice of Task structs. +func Export() ([]Task, error) { + cmd := exec.Command("task", "export", "rc.json.array=off") + out, err := cmd.Output() + if err != nil { + return nil, err + } + + var tasks []Task + scanner := bufio.NewScanner(bytes.NewReader(out)) + for scanner.Scan() { + line := scanner.Bytes() + line = bytes.TrimSpace(line) + if len(line) == 0 { + continue + } + var t Task + if err := json.Unmarshal(line, &t); err != nil { + return nil, err + } + tasks = append(tasks, t) + } + if err := scanner.Err(); err != nil { + return nil, err + } + return tasks, nil +} diff --git a/internal/task/task_test.go b/internal/task/task_test.go new file mode 100644 index 0000000..8940bfe --- /dev/null +++ b/internal/task/task_test.go @@ -0,0 +1,56 @@ +package task + +import ( + "os" + "testing" +) + +func TestAddAndExport(t *testing.T) { + tmp := t.TempDir() + if err := os.Setenv("TASKDATA", tmp); err != nil { + t.Fatal(err) + } + if err := os.Setenv("TASKRC", "/dev/null"); err != nil { + t.Fatal(err) + } + t.Cleanup(func() { + os.Unsetenv("TASKDATA") + os.Unsetenv("TASKRC") + }) + + if err := Add("hello world", []string{"tag", "anothertag", "tasksamuraitesting"}); err != nil { + t.Fatalf("add task 1: %v", err) + } + if err := Add("hello universe", []string{"foo", "tasksamuraitesting"}); err != nil { + t.Fatalf("add task 2: %v", err) + } + + tasks, err := Export() + if err != nil { + t.Fatalf("export: %v", err) + } + + found := make(map[string]bool) + for _, task := range tasks { + hasTag := false + for _, tag := range task.Tags { + if tag == "tasksamuraitesting" { + hasTag = true + break + } + } + if hasTag { + found[task.Description] = true + } + } + + if len(found) != 2 { + t.Fatalf("expected 2 tasks with tag, got %d", len(found)) + } + if !found["hello world"] { + t.Errorf("missing task 'hello world'") + } + if !found["hello universe"] { + t.Errorf("missing task 'hello universe'") + } +} -- cgit v1.2.3