diff options
| author | Paul Bütow <1224732+snonux@users.noreply.github.com> | 2025-06-19 23:43:20 +0300 |
|---|---|---|
| committer | Paul Bütow <1224732+snonux@users.noreply.github.com> | 2025-06-19 23:43:20 +0300 |
| commit | dee37364c1c690207cb12c399f65e2b53537b5a1 (patch) | |
| tree | b216ff2bc2cb5fdebbf0987ef5dfedef614eb2d1 /internal/task | |
| parent | 2235c13109b15f81a0c9635ae9133aaecb3d072a (diff) | |
Add Taskwarrior CLI tests
Diffstat (limited to 'internal/task')
| -rw-r--r-- | internal/task/task.go | 61 | ||||
| -rw-r--r-- | internal/task/task_test.go | 56 |
2 files changed, 117 insertions, 0 deletions
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'") + } +} |
