feat: add close/reopen and comment actions to issue detail view
Add SetIssueState client method and handler for toggling issue state
between open and closed via PATCH API. Add AddComment client method
wrapping PostComment. Register new routes POST /issues/{owner}/{repo}/{index}/state
and POST /issues/{owner}/{repo}/{index}/comments. Update issue_detail.html
template with comment form (HTMX inline append) and close/reopen button
(HTMX inline swap of state badge).
Closes leeworks-agents/gitea-mobile#29
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -241,6 +241,76 @@ func TestCloseIssue(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetIssueState(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
state string
|
||||
}{
|
||||
{"close", "closed"},
|
||||
{"reopen", "open"},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodPatch {
|
||||
t.Errorf("expected PATCH, got %s", r.Method)
|
||||
}
|
||||
if r.URL.Path != "/api/v1/repos/owner1/repo1/issues/42" {
|
||||
t.Errorf("unexpected path: %s", r.URL.Path)
|
||||
}
|
||||
|
||||
var body map[string]string
|
||||
if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
|
||||
t.Fatalf("failed to decode body: %v", err)
|
||||
}
|
||||
if body["state"] != tt.state {
|
||||
t.Errorf("expected state=%q, got %q", tt.state, body["state"])
|
||||
}
|
||||
|
||||
w.WriteHeader(http.StatusOK)
|
||||
json.NewEncoder(w).Encode(map[string]string{"state": tt.state})
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
c := NewClient(server.URL)
|
||||
c.setCache("issues-org1", "should-be-invalidated")
|
||||
|
||||
err := c.SetIssueState(context.Background(), "test-token", "owner1", "repo1", 42, tt.state)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
_, ok := c.getFromCache("issues-org1")
|
||||
if ok {
|
||||
t.Error("expected cache to be invalidated after SetIssueState")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAddComment(t *testing.T) {
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
comment := map[string]interface{}{
|
||||
"id": 1,
|
||||
"body": "test",
|
||||
"user": map[string]string{"login": "testuser"},
|
||||
"created_at": "2026-03-26T12:00:00Z",
|
||||
}
|
||||
json.NewEncoder(w).Encode(comment)
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
c := NewClient(server.URL)
|
||||
comment, err := c.AddComment(context.Background(), "test-token", "owner1", "repo1", 42, "test")
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if comment.Body != "test" {
|
||||
t.Errorf("comment.Body = %q, want %q", comment.Body, "test")
|
||||
}
|
||||
}
|
||||
|
||||
func TestPostComment(t *testing.T) {
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodPost {
|
||||
|
||||
Reference in New Issue
Block a user