180 lines
5.8 KiB
Go
180 lines
5.8 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"slices"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestListRepositoryUsersCombinesReviewerAndAssigneeEligibility(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
var request graphQLRequest
|
|
if err := json.NewDecoder(r.Body).Decode(&request); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
switch {
|
|
case strings.Contains(request.Query, "RepositoryReviewers"):
|
|
if request.Variables["after"] == nil {
|
|
_, _ = w.Write([]byte(`{"data":{"repository":{"collaborators":{
|
|
"pageInfo":{"hasNextPage":true,"endCursor":"next"},
|
|
"nodes":[
|
|
{"id":"u1","login":"alice","name":"Alice"},
|
|
{"id":"u2","login":"bob","name":"Bob"}
|
|
]
|
|
}}}}`))
|
|
} else {
|
|
_, _ = w.Write([]byte(`{"data":{"repository":{"collaborators":{
|
|
"pageInfo":{"hasNextPage":false},
|
|
"nodes":[{"id":"u4","login":"dave","name":"Dave"}]
|
|
}}}}`))
|
|
}
|
|
case strings.Contains(request.Query, "RepositoryAssignees"):
|
|
_, _ = w.Write([]byte(`{"data":{"repository":{"assignableUsers":{
|
|
"pageInfo":{"hasNextPage":false},
|
|
"nodes":[
|
|
{"id":"u2","login":"bob","name":"Bob"},
|
|
{"id":"u3","login":"carol","name":"Carol"}
|
|
]
|
|
}}}}`))
|
|
case strings.Contains(request.Query, "RepositoryContributions"):
|
|
_, _ = w.Write([]byte(`{"data":{"repository":{"defaultBranchRef":{"target":{"history":{
|
|
"nodes":[
|
|
{"committedDate":"2026-07-28T12:00:00Z","additions":42,
|
|
"author":{"user":{"login":"alice"}}},
|
|
{"committedDate":"2026-07-27T12:00:00Z","additions":8,
|
|
"author":{"user":{"login":"alice"}}},
|
|
{"committedDate":"2026-06-01T12:00:00Z","additions":5,
|
|
"author":{"user":{"login":"bob"}}}
|
|
]
|
|
}}}}}}`))
|
|
default:
|
|
t.Fatalf("unexpected query: %s", request.Query)
|
|
}
|
|
}))
|
|
defer server.Close()
|
|
|
|
client := NewGitHubClient(server.URL, "token")
|
|
users, err := client.ListRepositoryUsers(context.Background(), "o", "r")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(users) != 4 || users[0].Login != "alice" || !users[0].CanReview ||
|
|
users[0].CanAssign || users[1].Login != "bob" ||
|
|
!users[1].CanReview || !users[1].CanAssign ||
|
|
users[2].Login != "carol" || users[2].CanReview || !users[2].CanAssign ||
|
|
users[3].Login != "dave" || !users[3].CanReview {
|
|
t.Fatalf("repository users = %#v", users)
|
|
}
|
|
if users[0].RecentCommits != 2 || users[0].RecentAdditions != 50 ||
|
|
users[0].LastContributionAt.IsZero() || users[1].RecentCommits != 1 {
|
|
t.Fatalf("repository activity = %#v", users)
|
|
}
|
|
}
|
|
|
|
func TestAllAssigneesPaginates(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
var request graphQLRequest
|
|
if err := json.NewDecoder(r.Body).Decode(&request); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !strings.Contains(request.Query, "AssigneesPage") {
|
|
t.Fatalf("unexpected query: %s", request.Query)
|
|
}
|
|
_, _ = w.Write([]byte(`{"data":{"repository":{"pullRequest":{"assignees":{
|
|
"pageInfo":{"hasNextPage":false},
|
|
"nodes":[{"id":"u2","login":"bob","name":"Bob"}]
|
|
}}}}}`))
|
|
}))
|
|
defer server.Close()
|
|
|
|
client := NewGitHubClient(server.URL, "token")
|
|
users, err := client.allAssignees(
|
|
context.Background(), "o", "r", 1,
|
|
githubUserConnection{
|
|
PageInfo: githubPageInfo{HasNextPage: true, EndCursor: "next"},
|
|
Nodes: []githubActor{{Login: "alice"}},
|
|
},
|
|
)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(users) != 2 || users[0].Login != "alice" || users[1].Login != "bob" {
|
|
t.Fatalf("assignees = %#v", users)
|
|
}
|
|
}
|
|
|
|
func TestUpdatePullRequestPeoplePreservesUnchangedReviewers(t *testing.T) {
|
|
var requests []string
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
var input struct {
|
|
Reviewers []string `json:"reviewers"`
|
|
Assignees []string `json:"assignees"`
|
|
}
|
|
if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
switch {
|
|
case strings.HasSuffix(r.URL.Path, "/requested_reviewers"):
|
|
requests = append(requests, r.Method+":"+strings.Join(input.Reviewers, ","))
|
|
case strings.HasSuffix(r.URL.Path, "/issues/7"):
|
|
requests = append(requests, r.Method+":"+strings.Join(input.Assignees, ","))
|
|
default:
|
|
t.Fatalf("unexpected REST path: %s", r.URL.Path)
|
|
}
|
|
_, _ = w.Write([]byte(`{}`))
|
|
}))
|
|
defer server.Close()
|
|
|
|
client := NewGitHubClient(server.URL+"/api/graphql", "token")
|
|
people, err := client.UpdatePullRequestPeople(
|
|
context.Background(), "o", "r", 7,
|
|
PullRequestPeopleUpdate{
|
|
CurrentReviewers: []string{"keep", "remove"},
|
|
CurrentAssignees: []string{"alice"},
|
|
Reviewers: []string{"keep", "add"},
|
|
Assignees: []string{"alice", "bob"},
|
|
},
|
|
)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
want := []string{"POST:add", "DELETE:remove", "PATCH:alice,bob"}
|
|
if !slices.Equal(requests, want) {
|
|
t.Fatalf("REST requests = %v, want %v", requests, want)
|
|
}
|
|
if !slices.Equal(people.Reviewers, []string{"keep", "add"}) ||
|
|
!slices.Equal(people.Assignees, []string{"alice", "bob"}) {
|
|
t.Fatalf("updated people = %#v", people)
|
|
}
|
|
}
|
|
|
|
func TestUpdatePullRequestPeopleReportsSuccessfulPartialChanges(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method == http.MethodDelete {
|
|
http.Error(w, "cannot remove", http.StatusUnprocessableEntity)
|
|
return
|
|
}
|
|
_, _ = w.Write([]byte(`{}`))
|
|
}))
|
|
defer server.Close()
|
|
|
|
client := NewGitHubClient(server.URL+"/api/graphql", "token")
|
|
people, err := client.UpdatePullRequestPeople(
|
|
context.Background(), "o", "r", 7,
|
|
PullRequestPeopleUpdate{
|
|
CurrentReviewers: []string{"keep", "remove"},
|
|
Reviewers: []string{"keep", "add"},
|
|
},
|
|
)
|
|
if err == nil || !strings.Contains(err.Error(), "remove reviewers") {
|
|
t.Fatalf("partial update error = %v", err)
|
|
}
|
|
if !equalLoginSets(people.Reviewers, []string{"keep", "remove", "add"}) {
|
|
t.Fatalf("partial reviewer state = %#v", people.Reviewers)
|
|
}
|
|
}
|