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