test: command method edge cases — agentic 66.4%, 524 tests

Add error path tests for all forge commands (API errors, missing args),
PR with body, issue create with labels/milestones, workspace clean filters.

Coverage: agentic 65.1% → 66.4% (+1.3pp)

Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
Snider 2026-03-25 00:56:19 +00:00
parent 3d7adb91eb
commit cf68371421

View file

@ -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())