1package tools
2
3import (
4 "context"
5 "encoding/json"
6 "testing"
7
8 "github.com/bnema/zut/packages/core"
9)
10
11func TestUpdateGoalToolReturnsPersistableStatus(t *testing.T) {
12 tool := &UpdateGoalTool{}
13 raw, err := json.Marshal(map[string]string{"status": "complete"})
14 if err != nil {
15 t.Fatal(err)
16 }
17 result, err := tool.Execute(context.Background(), raw, nil)
18 if err != nil {
19 t.Fatal(err)
20 }
21 if result.IsError {
22 t.Fatalf("result = %#v, want success", result)
23 }
24 update, ok := GoalUpdateFromResult(result)
25 if !ok {
26 t.Fatalf("details = %#v, want goal update", result.Details)
27 }
28 if update.Status != core.GoalDone || update.Reason != "" {
29 t.Fatalf("update = %#v", update)
30 }
31}
32
33func TestUpdateGoalToolReturnsPersistableManagerGoal(t *testing.T) {
34 tool := &UpdateGoalTool{}
35 result, err := tool.Execute(context.Background(), json.RawMessage(`{"status":"active","objective":"reproduce the reported failure"}`), nil)
36 if err != nil {
37 t.Fatal(err)
38 }
39 update, ok := GoalUpdateFromResult(result)
40 if !ok {
41 t.Fatalf("details = %#v, want goal update", result.Details)
42 }
43 if update.Status != core.GoalActive || update.Objective != "reproduce the reported failure" {
44 t.Fatalf("update = %#v", update)
45 }
46}
47
48func TestUpdateGoalToolRejectsUnknownFields(t *testing.T) {
49 tool := &UpdateGoalTool{}
50 result, err := tool.Execute(context.Background(), json.RawMessage(`{"status":"complete","unexpected":true}`), nil)
51 if err != nil {
52 t.Fatal(err)
53 }
54 if !result.IsError {
55 t.Fatalf("result = %#v, want tool error", result)
56 }
57}
58
59func TestGoalUpdateFromResultRejectsBlockedWithoutReason(t *testing.T) {
60 result := core.ToolResult{Details: GoalUpdate{Status: core.GoalBlocked}}
61 if _, ok := GoalUpdateFromResult(result); ok {
62 t.Fatal("blank-reason blocked update was accepted")
63 }
64
65 result.Details = GoalUpdate{Status: core.GoalBlocked, Reason: "needs user input"}
66 if _, ok := GoalUpdateFromResult(result); !ok {
67 t.Fatal("blocked update with reason was rejected")
68 }
69
70 result.Details = GoalUpdate{Status: core.GoalDone}
71 if _, ok := GoalUpdateFromResult(result); !ok {
72 t.Fatal("completed update without reason was rejected")
73 }
74}
75
76func TestUpdateGoalToolRejectsUnsupportedStatus(t *testing.T) {
77 tool := &UpdateGoalTool{}
78 raw := json.RawMessage(`{"status":"active"}`)
79 result, err := tool.Execute(context.Background(), raw, nil)
80 if err != nil {
81 t.Fatal(err)
82 }
83 if !result.IsError {
84 t.Fatalf("result = %#v, want tool error", result)
85 }
86 if _, ok := GoalUpdateFromResult(result); ok {
87 t.Fatal("invalid result exposed a goal update")
88 }
89}