Compare commits

..

1 Commits

Author SHA1 Message Date
agent-company d0bcbd1ed0 feat: add POST /pulls/{owner}/{repo}/{index}/assignees route
Build and Push / test (pull_request) Successful in 1m46s
Build and Push / build (pull_request) Has been skipped
Register the PR assignees route pointing to the existing AssignIssue
handler, which works for both issues and PRs via the Gitea API.
Add integration tests covering valid, HTMX, and missing assignee cases.

Closes leeworks-agents/gitea-mobile#228

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-05-18 21:39:34 +00:00
2 changed files with 61 additions and 72 deletions
+1
View File
@@ -56,6 +56,7 @@ func (h *Handler) RegisterRoutes(mux *http.ServeMux) {
mux.HandleFunc("GET /pulls/{owner}/{repo}/{index}", h.PullDetail)
mux.HandleFunc("POST /pulls/{owner}/{repo}/{index}/review", h.SubmitReview)
mux.HandleFunc("POST /pulls/{owner}/{repo}/{index}/state", h.SetPullState)
mux.HandleFunc("POST /pulls/{owner}/{repo}/{index}/assignees", h.AssignIssue)
// Settings (handled separately for auth bypass).
settingsHandler := &SettingsHandler{
+60 -72
View File
@@ -489,78 +489,6 @@ func TestIntegration_PullDetail_InvalidIndex(t *testing.T) {
}
}
// --- Issue #217: HTMX fragment assertions for IssueDetail and PullDetail ---
func TestIntegration_IssueDetail_HTMX(t *testing.T) {
h, srv := newTestHandlerWithMock(t)
defer srv.Close()
mux := http.NewServeMux()
mux.HandleFunc("GET /issues/{owner}/{repo}/{index}", h.IssueDetail)
req := reqWithToken(http.MethodGet, "/issues/test-org/repo1/1", "")
req.Header.Set("HX-Request", "true")
w := httptest.NewRecorder()
mux.ServeHTTP(w, req)
if w.Code != http.StatusOK {
t.Errorf("status = %d, want %d", w.Code, http.StatusOK)
}
body := w.Body.String()
// HTMX response must NOT contain layout boilerplate.
if contains(body, "<html") {
t.Error("HTMX response should not contain <html tag")
}
if contains(body, "<!DOCTYPE") {
t.Error("HTMX response should not contain <!DOCTYPE")
}
if contains(body, `class="bottom-nav"`) {
t.Error("HTMX response should not contain bottom-nav")
}
// HTMX response MUST contain issue-specific content.
if !contains(body, "Test issue #1") {
t.Errorf("expected issue title 'Test issue #1' in HTMX fragment, got: %s", body[:min(300, len(body))])
}
}
func TestIntegration_PullDetail_HTMX(t *testing.T) {
h, srv := newTestHandlerWithMock(t)
defer srv.Close()
mux := http.NewServeMux()
mux.HandleFunc("GET /pulls/{owner}/{repo}/{index}", h.PullDetail)
req := reqWithToken(http.MethodGet, "/pulls/test-org/repo1/1", "")
req.Header.Set("HX-Request", "true")
w := httptest.NewRecorder()
mux.ServeHTTP(w, req)
if w.Code != http.StatusOK {
t.Errorf("status = %d, want %d", w.Code, http.StatusOK)
}
body := w.Body.String()
// HTMX response must NOT contain layout boilerplate.
if contains(body, "<html") {
t.Error("HTMX response should not contain <html tag")
}
if contains(body, "<!DOCTYPE") {
t.Error("HTMX response should not contain <!DOCTYPE")
}
if contains(body, `class="bottom-nav"`) {
t.Error("HTMX response should not contain bottom-nav")
}
// HTMX response MUST contain PR-specific content.
if !contains(body, "Test PR #1") {
t.Errorf("expected PR title 'Test PR #1' in HTMX fragment, got: %s", body[:min(300, len(body))])
}
}
// --- Issue #138: Integration tests for GET /issues/new and GET /issues/new/labels ---
func TestIntegration_NewIssue_WithToken(t *testing.T) {
@@ -798,6 +726,66 @@ func TestIntegration_AssignIssue_MissingAssignee(t *testing.T) {
}
}
// --- Issue #228: Integration tests for POST /pulls/{owner}/{repo}/{index}/assignees ---
func TestIntegration_AssignPull_Valid(t *testing.T) {
h, srv := newTestHandlerWithMock(t)
defer srv.Close()
mux := http.NewServeMux()
mux.HandleFunc("POST /pulls/{owner}/{repo}/{index}/assignees", h.AssignIssue)
form := url.Values{"assignee": {"user1"}}
req := reqWithToken(http.MethodPost, "/pulls/test-org/repo1/1/assignees", form.Encode())
w := httptest.NewRecorder()
mux.ServeHTTP(w, req)
if w.Code != http.StatusSeeOther {
t.Errorf("status = %d, want %d", w.Code, http.StatusSeeOther)
}
}
func TestIntegration_AssignPull_HTMX(t *testing.T) {
h, srv := newTestHandlerWithMock(t)
defer srv.Close()
mux := http.NewServeMux()
mux.HandleFunc("POST /pulls/{owner}/{repo}/{index}/assignees", h.AssignIssue)
form := url.Values{"assignee": {"user1"}}
req := reqWithToken(http.MethodPost, "/pulls/test-org/repo1/1/assignees", form.Encode())
req.Header.Set("HX-Request", "true")
w := httptest.NewRecorder()
mux.ServeHTTP(w, req)
if w.Code != http.StatusOK {
t.Errorf("status = %d, want %d", w.Code, http.StatusOK)
}
body := w.Body.String()
if !contains(body, "Assigned to user1") {
t.Errorf("expected 'Assigned to user1' in HTMX response, got: %s", body)
}
}
func TestIntegration_AssignPull_MissingAssignee(t *testing.T) {
h, srv := newTestHandlerWithMock(t)
defer srv.Close()
mux := http.NewServeMux()
mux.HandleFunc("POST /pulls/{owner}/{repo}/{index}/assignees", h.AssignIssue)
req := reqWithToken(http.MethodPost, "/pulls/test-org/repo1/1/assignees", "")
w := httptest.NewRecorder()
mux.ServeHTTP(w, req)
if w.Code != http.StatusBadRequest {
t.Errorf("status = %d, want %d", w.Code, http.StatusBadRequest)
}
}
// --- Issue #118: Integration tests for CloseIssue and AddComment ---
func TestIntegration_CloseIssue(t *testing.T) {