diff --git a/pkg/agentic/commands_test.go b/pkg/agentic/commands_test.go index c97c1b8..810b3d7 100644 --- a/pkg/agentic/commands_test.go +++ b/pkg/agentic/commands_test.go @@ -165,6 +165,60 @@ func TestCmdIssueCreate_Good_Success(t *testing.T) { assert.True(t, r.OK) } +func TestCmdIssueCreate_Good_WithLabelsAndMilestone(t *testing.T) { + callPaths := []string{} + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + callPaths = append(callPaths, r.URL.Path) + switch { + case r.URL.Path == "/api/v1/repos/core/go-io/milestones": + json.NewEncoder(w).Encode([]map[string]any{ + {"id": 1, "title": "v0.8.0"}, + {"id": 2, "title": "v0.9.0"}, + }) + case r.URL.Path == "/api/v1/repos/core/go-io/labels": + json.NewEncoder(w).Encode([]map[string]any{ + {"id": 10, "name": "agentic"}, + {"id": 11, "name": "bug"}, + }) + default: + json.NewEncoder(w).Encode(map[string]any{ + "number": 15, "title": "Full issue", "html_url": "https://forge.test/issues/15", + }) + } + })) + t.Cleanup(srv.Close) + + s, _ := testPrepWithCore(t, srv) + r := s.cmdIssueCreate(core.NewOptions( + core.Option{Key: "_arg", Value: "go-io"}, + core.Option{Key: "title", Value: "Full issue"}, + core.Option{Key: "labels", Value: "agentic,bug"}, + core.Option{Key: "milestone", Value: "v0.8.0"}, + core.Option{Key: "ref", Value: "dev"}, + )) + assert.True(t, r.OK) +} + +func TestCmdIssueCreate_Bad_APIError(t *testing.T) { + callCount := 0 + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + callCount++ + if callCount <= 2 { + json.NewEncoder(w).Encode([]map[string]any{}) // milestones/labels + } else { + w.WriteHeader(500) + } + })) + t.Cleanup(srv.Close) + + s, _ := testPrepWithCore(t, srv) + r := s.cmdIssueCreate(core.NewOptions( + core.Option{Key: "_arg", Value: "go-io"}, + core.Option{Key: "title", Value: "Fail"}, + )) + assert.False(t, r.OK) +} + func TestCmdPRGet_Bad_MissingArgs(t *testing.T) { s, _ := testPrepWithCore(t, nil) r := s.cmdPRGet(core.NewOptions()) @@ -175,7 +229,7 @@ func TestCmdPRGet_Good_Success(t *testing.T) { srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { json.NewEncoder(w).Encode(map[string]any{ "number": 3, "title": "Fix", "state": "open", "mergeable": true, - "html_url": "https://forge.test/pulls/3", "body": "", + "html_url": "https://forge.test/pulls/3", "body": "PR body here", "head": map[string]any{"ref": "fix/it"}, "base": map[string]any{"ref": "dev"}, }) })) @@ -189,6 +243,142 @@ func TestCmdPRGet_Good_Success(t *testing.T) { assert.True(t, r.OK) } +func TestCmdPRGet_Bad_APIError(t *testing.T) { + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(404) + })) + t.Cleanup(srv.Close) + + s, _ := testPrepWithCore(t, srv) + r := s.cmdPRGet(core.NewOptions( + core.Option{Key: "_arg", Value: "go-io"}, + core.Option{Key: "number", Value: "99"}, + )) + assert.False(t, r.OK) +} + +func TestCmdPRList_Good_WithPRs(t *testing.T) { + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + json.NewEncoder(w).Encode([]map[string]any{ + {"number": 1, "title": "Fix", "state": "open", + "head": map[string]any{"ref": "fix/a"}, "base": map[string]any{"ref": "dev"}}, + {"number": 2, "title": "Feat", "state": "closed", + "head": map[string]any{"ref": "feat/b"}, "base": map[string]any{"ref": "dev"}}, + }) + })) + t.Cleanup(srv.Close) + + s, _ := testPrepWithCore(t, srv) + r := s.cmdPRList(core.NewOptions(core.Option{Key: "_arg", Value: "go-io"})) + assert.True(t, r.OK) +} + +func TestCmdPRList_Bad_APIError(t *testing.T) { + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(500) + })) + t.Cleanup(srv.Close) + + s, _ := testPrepWithCore(t, srv) + r := s.cmdPRList(core.NewOptions(core.Option{Key: "_arg", Value: "go-io"})) + assert.False(t, r.OK) +} + +func TestCmdPRMerge_Bad_APIError(t *testing.T) { + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(409) + json.NewEncoder(w).Encode(map[string]any{"message": "conflict"}) + })) + t.Cleanup(srv.Close) + + s, _ := testPrepWithCore(t, srv) + r := s.cmdPRMerge(core.NewOptions( + core.Option{Key: "_arg", Value: "go-io"}, + core.Option{Key: "number", Value: "5"}, + )) + assert.False(t, r.OK) +} + +func TestCmdPRMerge_Good_CustomMethod(t *testing.T) { + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(200) + })) + t.Cleanup(srv.Close) + + s, _ := testPrepWithCore(t, srv) + r := s.cmdPRMerge(core.NewOptions( + core.Option{Key: "_arg", Value: "go-io"}, + core.Option{Key: "number", Value: "5"}, + core.Option{Key: "method", Value: "squash"}, + )) + assert.True(t, r.OK) +} + +func TestCmdIssueGet_Good_WithBody(t *testing.T) { + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + json.NewEncoder(w).Encode(map[string]any{ + "number": 1, "title": "Bug", "state": "open", + "html_url": "https://forge.test/issues/1", "body": "Detailed description", + }) + })) + t.Cleanup(srv.Close) + + s, _ := testPrepWithCore(t, srv) + r := s.cmdIssueGet(core.NewOptions( + core.Option{Key: "_arg", Value: "go-io"}, + core.Option{Key: "number", Value: "1"}, + )) + assert.True(t, r.OK) +} + +func TestCmdIssueList_Bad_APIError(t *testing.T) { + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(500) + })) + t.Cleanup(srv.Close) + + s, _ := testPrepWithCore(t, srv) + r := s.cmdIssueList(core.NewOptions(core.Option{Key: "_arg", Value: "go-io"})) + assert.False(t, r.OK) +} + +func TestCmdIssueComment_Bad_APIError(t *testing.T) { + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(500) + })) + t.Cleanup(srv.Close) + + s, _ := testPrepWithCore(t, srv) + r := s.cmdIssueComment(core.NewOptions( + core.Option{Key: "_arg", Value: "go-io"}, + core.Option{Key: "number", Value: "1"}, + core.Option{Key: "body", Value: "test"}, + )) + assert.False(t, r.OK) +} + +func TestCmdRepoGet_Bad_APIError(t *testing.T) { + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(500) + })) + t.Cleanup(srv.Close) + + s, _ := testPrepWithCore(t, srv) + r := s.cmdRepoGet(core.NewOptions(core.Option{Key: "_arg", Value: "go-io"})) + assert.False(t, r.OK) +} + +func TestCmdRepoList_Bad_APIError(t *testing.T) { + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(500) + })) + t.Cleanup(srv.Close) + + s, _ := testPrepWithCore(t, srv) + r := s.cmdRepoList(core.NewOptions()) + assert.False(t, r.OK) +} + func TestCmdPRList_Bad_MissingRepo(t *testing.T) { s, _ := testPrepWithCore(t, nil) r := s.cmdPRList(core.NewOptions())