Files
ai-agent/internal/agents/task/agent_test.go
Christoph K. b1a576f61e tests
2026-03-20 07:08:00 +01:00

237 lines
6.3 KiB
Go

package task
import (
"os"
"strings"
"testing"
"time"
"my-brain-importer/internal/agents"
)
func newTestAgent(t *testing.T) (*Agent, func()) {
t.Helper()
f, err := os.CreateTemp("", "tasks_agent_*.json")
if err != nil {
t.Fatalf("temp-Datei: %v", err)
}
name := f.Name()
f.Close()
os.Remove(name) // Datei entfernen → loadLocked gibt leeres Slice zurück
a := &Agent{store: &Store{path: name}}
return a, func() { os.Remove(name) }
}
// ── parseAddArgs ─────────────────────────────────────────────────────────────
func TestParseAddArgs_TextOnly(t *testing.T) {
text, prio, due := parseAddArgs([]string{"Arzttermin", "buchen"})
if text != "Arzttermin buchen" {
t.Errorf("text: %q", text)
}
if prio != "" {
t.Errorf("prio sollte leer sein: %q", prio)
}
if due != nil {
t.Error("due sollte nil sein")
}
}
func TestParseAddArgs_AllFlags(t *testing.T) {
text, prio, due := parseAddArgs([]string{"Zahnarzt", "--due", "2026-12-01", "--priority", "hoch"})
if text != "Zahnarzt" {
t.Errorf("text: %q", text)
}
if prio != "hoch" {
t.Errorf("prio: %q", prio)
}
if due == nil {
t.Fatal("due sollte gesetzt sein")
}
if due.Format("2006-01-02") != "2026-12-01" {
t.Errorf("due: %v", due)
}
}
func TestParseAddArgs_ShortFlags(t *testing.T) {
text, prio, due := parseAddArgs([]string{"Meeting", "-p", "mittel", "-d", "2026-06-15"})
if text != "Meeting" {
t.Errorf("text: %q", text)
}
if prio != "mittel" {
t.Errorf("prio: %q", prio)
}
if due == nil || due.Format("2006-01-02") != "2026-06-15" {
t.Errorf("due: %v", due)
}
}
func TestParseAddArgs_InvalidDate(t *testing.T) {
_, _, due := parseAddArgs([]string{"Task", "--due", "kein-datum"})
if due != nil {
t.Error("ungültiges Datum sollte nil ergeben")
}
}
// ── Agent.Handle ─────────────────────────────────────────────────────────────
func TestAgent_Add(t *testing.T) {
a, cleanup := newTestAgent(t)
defer cleanup()
resp := a.Handle(agents.Request{Action: agents.ActionAdd, Args: []string{"Mein Task"}})
if resp.Error != nil {
t.Fatalf("Add: %v", resp.Error)
}
if !strings.Contains(resp.Text, "Mein Task") {
t.Errorf("Antwort enthält keinen Task-Text: %q", resp.Text)
}
}
func TestAgent_Add_WithDueAndPriority(t *testing.T) {
a, cleanup := newTestAgent(t)
defer cleanup()
resp := a.Handle(agents.Request{
Action: agents.ActionAdd,
Args: []string{"Frist", "--due", "2026-12-31", "--priority", "hoch"},
})
if resp.Error != nil {
t.Fatalf("Add: %v", resp.Error)
}
if !strings.Contains(resp.Text, "Frist") {
t.Errorf("Task-Text fehlt: %q", resp.Text)
}
if !strings.Contains(resp.Text, "hoch") {
t.Errorf("Priorität fehlt: %q", resp.Text)
}
if !strings.Contains(resp.Text, "31.12.2026") {
t.Errorf("Datum fehlt: %q", resp.Text)
}
}
func TestAgent_Add_NoArgs(t *testing.T) {
a, cleanup := newTestAgent(t)
defer cleanup()
resp := a.Handle(agents.Request{Action: agents.ActionAdd, Args: []string{}})
if !strings.Contains(resp.Text, "❌") {
t.Errorf("erwartet Fehlermeldung, got: %q", resp.Text)
}
}
func TestAgent_List_Empty(t *testing.T) {
a, cleanup := newTestAgent(t)
defer cleanup()
resp := a.Handle(agents.Request{Action: agents.ActionList})
if !strings.Contains(resp.Text, "Keine Tasks") {
t.Errorf("erwartet 'Keine Tasks': %q", resp.Text)
}
}
func TestAgent_List_ShowsDueDate(t *testing.T) {
a, cleanup := newTestAgent(t)
defer cleanup()
due := time.Now().Add(48 * time.Hour) // übermorgen
a.store.Add("Übermorgen", "", &due)
resp := a.Handle(agents.Request{Action: agents.ActionList})
if !strings.Contains(resp.Text, "📅") {
t.Errorf("Datum-Icon fehlt in Liste: %q", resp.Text)
}
}
func TestAgent_List_ShowsOverdue(t *testing.T) {
a, cleanup := newTestAgent(t)
defer cleanup()
past := time.Now().Add(-48 * time.Hour) // vorgestern
a.store.Add("Überfällig", "", &past)
resp := a.Handle(agents.Request{Action: agents.ActionList})
if !strings.Contains(resp.Text, "ÜBERFÄLLIG") {
t.Errorf("ÜBERFÄLLIG fehlt: %q", resp.Text)
}
}
func TestAgent_Done(t *testing.T) {
a, cleanup := newTestAgent(t)
defer cleanup()
addResp := a.Handle(agents.Request{Action: agents.ActionAdd, Args: []string{"Erledigen"}})
// Short-ID aus Antwort extrahieren
tasks, _ := a.store.Load()
if len(tasks) == 0 {
t.Fatal("kein Task angelegt")
}
id := tasks[0].ID
shortID := id[len(id)-6:]
_ = addResp
resp := a.Handle(agents.Request{Action: agents.ActionDone, Args: []string{shortID}})
if resp.Error != nil {
t.Fatalf("Done: %v", resp.Error)
}
if !strings.Contains(resp.Text, "✅") {
t.Errorf("erwartet ✅: %q", resp.Text)
}
}
func TestAgent_Delete(t *testing.T) {
a, cleanup := newTestAgent(t)
defer cleanup()
a.Handle(agents.Request{Action: agents.ActionAdd, Args: []string{"Löschen"}})
tasks, _ := a.store.Load()
id := tasks[0].ID
shortID := id[len(id)-6:]
resp := a.Handle(agents.Request{Action: agents.ActionDelete, Args: []string{shortID}})
if resp.Error != nil {
t.Fatalf("Delete: %v", resp.Error)
}
if !strings.Contains(resp.Text, "🗑️") {
t.Errorf("erwartet 🗑️: %q", resp.Text)
}
tasks, _ = a.store.Load()
if len(tasks) != 0 {
t.Errorf("Task sollte gelöscht sein, noch %d vorhanden", len(tasks))
}
}
func TestAgent_UnknownAction(t *testing.T) {
a, cleanup := newTestAgent(t)
defer cleanup()
resp := a.Handle(agents.Request{Action: "unknown"})
if !strings.Contains(resp.Text, "❌") {
t.Errorf("erwartet Fehlermeldung: %q", resp.Text)
}
}
// ── resolveID ────────────────────────────────────────────────────────────────
func TestResolveID_FullMatch(t *testing.T) {
tasks := []Task{{ID: "123456789"}}
if got := resolveID(tasks, "123456789"); got != "123456789" {
t.Errorf("got %q", got)
}
}
func TestResolveID_ShortMatch(t *testing.T) {
tasks := []Task{{ID: "123456789"}}
if got := resolveID(tasks, "456789"); got != "123456789" {
t.Errorf("got %q", got)
}
}
func TestResolveID_NotFound(t *testing.T) {
tasks := []Task{{ID: "123456789"}}
if got := resolveID(tasks, "000000"); got != "" {
t.Errorf("erwartet leer, got %q", got)
}
}