cli/api/queries_repo_test.go
2021-08-25 12:41:30 +02:00

343 lines
9.3 KiB
Go

package api
import (
"io"
"net/http"
"strings"
"testing"
"github.com/cli/cli/v2/internal/ghrepo"
"github.com/cli/cli/v2/pkg/httpmock"
)
func Test_RepoMetadata(t *testing.T) {
http := &httpmock.Registry{}
client := NewClient(ReplaceTripper(http))
repo, _ := ghrepo.FromFullName("OWNER/REPO")
input := RepoMetadataInput{
Assignees: true,
Reviewers: true,
Labels: true,
Projects: true,
Milestones: true,
}
http.Register(
httpmock.GraphQL(`query RepositoryAssignableUsers\b`),
httpmock.StringResponse(`
{ "data": { "repository": { "assignableUsers": {
"nodes": [
{ "login": "hubot", "id": "HUBOTID" },
{ "login": "MonaLisa", "id": "MONAID" }
],
"pageInfo": { "hasNextPage": false }
} } } }
`))
http.Register(
httpmock.GraphQL(`query RepositoryLabelList\b`),
httpmock.StringResponse(`
{ "data": { "repository": { "labels": {
"nodes": [
{ "name": "feature", "id": "FEATUREID" },
{ "name": "TODO", "id": "TODOID" },
{ "name": "bug", "id": "BUGID" }
],
"pageInfo": { "hasNextPage": false }
} } } }
`))
http.Register(
httpmock.GraphQL(`query RepositoryMilestoneList\b`),
httpmock.StringResponse(`
{ "data": { "repository": { "milestones": {
"nodes": [
{ "title": "GA", "id": "GAID" },
{ "title": "Big One.oh", "id": "BIGONEID" }
],
"pageInfo": { "hasNextPage": false }
} } } }
`))
http.Register(
httpmock.GraphQL(`query RepositoryProjectList\b`),
httpmock.StringResponse(`
{ "data": { "repository": { "projects": {
"nodes": [
{ "name": "Cleanup", "id": "CLEANUPID" },
{ "name": "Roadmap", "id": "ROADMAPID" }
],
"pageInfo": { "hasNextPage": false }
} } } }
`))
http.Register(
httpmock.GraphQL(`query OrganizationProjectList\b`),
httpmock.StringResponse(`
{ "data": { "organization": { "projects": {
"nodes": [
{ "name": "Triage", "id": "TRIAGEID" }
],
"pageInfo": { "hasNextPage": false }
} } } }
`))
http.Register(
httpmock.GraphQL(`query OrganizationTeamList\b`),
httpmock.StringResponse(`
{ "data": { "organization": { "teams": {
"nodes": [
{ "slug": "owners", "id": "OWNERSID" },
{ "slug": "Core", "id": "COREID" }
],
"pageInfo": { "hasNextPage": false }
} } } }
`))
result, err := RepoMetadata(client, repo, input)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
expectedMemberIDs := []string{"MONAID", "HUBOTID"}
memberIDs, err := result.MembersToIDs([]string{"monalisa", "hubot"})
if err != nil {
t.Errorf("error resolving members: %v", err)
}
if !sliceEqual(memberIDs, expectedMemberIDs) {
t.Errorf("expected members %v, got %v", expectedMemberIDs, memberIDs)
}
expectedTeamIDs := []string{"COREID", "OWNERSID"}
teamIDs, err := result.TeamsToIDs([]string{"OWNER/core", "/owners"})
if err != nil {
t.Errorf("error resolving teams: %v", err)
}
if !sliceEqual(teamIDs, expectedTeamIDs) {
t.Errorf("expected teams %v, got %v", expectedTeamIDs, teamIDs)
}
expectedLabelIDs := []string{"BUGID", "TODOID"}
labelIDs, err := result.LabelsToIDs([]string{"bug", "todo"})
if err != nil {
t.Errorf("error resolving labels: %v", err)
}
if !sliceEqual(labelIDs, expectedLabelIDs) {
t.Errorf("expected labels %v, got %v", expectedLabelIDs, labelIDs)
}
expectedProjectIDs := []string{"TRIAGEID", "ROADMAPID"}
projectIDs, err := result.ProjectsToIDs([]string{"triage", "roadmap"})
if err != nil {
t.Errorf("error resolving projects: %v", err)
}
if !sliceEqual(projectIDs, expectedProjectIDs) {
t.Errorf("expected projects %v, got %v", expectedProjectIDs, projectIDs)
}
expectedMilestoneID := "BIGONEID"
milestoneID, err := result.MilestoneToID("big one.oh")
if err != nil {
t.Errorf("error resolving milestone: %v", err)
}
if milestoneID != expectedMilestoneID {
t.Errorf("expected milestone %v, got %v", expectedMilestoneID, milestoneID)
}
}
func Test_ProjectsToPaths(t *testing.T) {
expectedProjectPaths := []string{"OWNER/REPO/PROJECT_NUMBER", "ORG/PROJECT_NUMBER"}
projects := []RepoProject{
{ID: "id1", Name: "My Project", ResourcePath: "/OWNER/REPO/projects/PROJECT_NUMBER"},
{ID: "id2", Name: "Org Project", ResourcePath: "/orgs/ORG/projects/PROJECT_NUMBER"},
{ID: "id3", Name: "Project", ResourcePath: "/orgs/ORG/projects/PROJECT_NUMBER_2"},
}
projectNames := []string{"My Project", "Org Project"}
projectPaths, err := ProjectsToPaths(projects, projectNames)
if err != nil {
t.Errorf("error resolving projects: %v", err)
}
if !sliceEqual(projectPaths, expectedProjectPaths) {
t.Errorf("expected projects %v, got %v", expectedProjectPaths, projectPaths)
}
}
func Test_ProjectNamesToPaths(t *testing.T) {
http := &httpmock.Registry{}
client := NewClient(ReplaceTripper(http))
repo, _ := ghrepo.FromFullName("OWNER/REPO")
http.Register(
httpmock.GraphQL(`query RepositoryProjectList\b`),
httpmock.StringResponse(`
{ "data": { "repository": { "projects": {
"nodes": [
{ "name": "Cleanup", "id": "CLEANUPID", "resourcePath": "/OWNER/REPO/projects/1" },
{ "name": "Roadmap", "id": "ROADMAPID", "resourcePath": "/OWNER/REPO/projects/2" }
],
"pageInfo": { "hasNextPage": false }
} } } }
`))
http.Register(
httpmock.GraphQL(`query OrganizationProjectList\b`),
httpmock.StringResponse(`
{ "data": { "organization": { "projects": {
"nodes": [
{ "name": "Triage", "id": "TRIAGEID", "resourcePath": "/orgs/ORG/projects/1" }
],
"pageInfo": { "hasNextPage": false }
} } } }
`))
projectPaths, err := ProjectNamesToPaths(client, repo, []string{"Triage", "Roadmap"})
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
expectedProjectPaths := []string{"ORG/1", "OWNER/REPO/2"}
if !sliceEqual(projectPaths, expectedProjectPaths) {
t.Errorf("expected projects paths %v, got %v", expectedProjectPaths, projectPaths)
}
}
func Test_RepoResolveMetadataIDs(t *testing.T) {
http := &httpmock.Registry{}
client := NewClient(ReplaceTripper(http))
repo, _ := ghrepo.FromFullName("OWNER/REPO")
input := RepoResolveInput{
Assignees: []string{"monalisa", "hubot"},
Reviewers: []string{"monalisa", "octocat", "OWNER/core", "/robots"},
Labels: []string{"bug", "help wanted"},
}
expectedQuery := `query RepositoryResolveMetadataIDs {
u000: user(login:"monalisa"){id,login}
u001: user(login:"hubot"){id,login}
u002: user(login:"octocat"){id,login}
repository(owner:"OWNER",name:"REPO"){
l000: label(name:"bug"){id,name}
l001: label(name:"help wanted"){id,name}
}
organization(login:"OWNER"){
t000: team(slug:"core"){id,slug}
t001: team(slug:"robots"){id,slug}
}
}
`
responseJSON := `
{ "data": {
"u000": { "login": "MonaLisa", "id": "MONAID" },
"u001": { "login": "hubot", "id": "HUBOTID" },
"u002": { "login": "octocat", "id": "OCTOID" },
"repository": {
"l000": { "name": "bug", "id": "BUGID" },
"l001": { "name": "Help Wanted", "id": "HELPID" }
},
"organization": {
"t000": { "slug": "core", "id": "COREID" },
"t001": { "slug": "Robots", "id": "ROBOTID" }
}
} }
`
http.Register(
httpmock.GraphQL(`query RepositoryResolveMetadataIDs\b`),
httpmock.GraphQLQuery(responseJSON, func(q string, _ map[string]interface{}) {
if q != expectedQuery {
t.Errorf("expected query %q, got %q", expectedQuery, q)
}
}))
result, err := RepoResolveMetadataIDs(client, repo, input)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
expectedMemberIDs := []string{"MONAID", "HUBOTID", "OCTOID"}
memberIDs, err := result.MembersToIDs([]string{"monalisa", "hubot", "octocat"})
if err != nil {
t.Errorf("error resolving members: %v", err)
}
if !sliceEqual(memberIDs, expectedMemberIDs) {
t.Errorf("expected members %v, got %v", expectedMemberIDs, memberIDs)
}
expectedTeamIDs := []string{"COREID", "ROBOTID"}
teamIDs, err := result.TeamsToIDs([]string{"/core", "/robots"})
if err != nil {
t.Errorf("error resolving teams: %v", err)
}
if !sliceEqual(teamIDs, expectedTeamIDs) {
t.Errorf("expected members %v, got %v", expectedTeamIDs, teamIDs)
}
expectedLabelIDs := []string{"BUGID", "HELPID"}
labelIDs, err := result.LabelsToIDs([]string{"bug", "help wanted"})
if err != nil {
t.Errorf("error resolving labels: %v", err)
}
if !sliceEqual(labelIDs, expectedLabelIDs) {
t.Errorf("expected members %v, got %v", expectedLabelIDs, labelIDs)
}
}
func sliceEqual(a, b []string) bool {
if len(a) != len(b) {
return false
}
for i := range a {
if a[i] != b[i] {
return false
}
}
return true
}
func Test_RepoMilestones(t *testing.T) {
tests := []struct {
state string
want string
wantErr bool
}{
{
state: "open",
want: `"states":["OPEN"]`,
},
{
state: "closed",
want: `"states":["CLOSED"]`,
},
{
state: "all",
want: `"states":["OPEN","CLOSED"]`,
},
{
state: "invalid state",
wantErr: true,
},
}
for _, tt := range tests {
var query string
reg := &httpmock.Registry{}
reg.Register(httpmock.MatchAny, func(req *http.Request) (*http.Response, error) {
buf := new(strings.Builder)
_, err := io.Copy(buf, req.Body)
if err != nil {
return nil, err
}
query = buf.String()
return httpmock.StringResponse("{}")(req)
})
client := NewClient(ReplaceTripper(reg))
_, err := RepoMilestones(client, ghrepo.New("OWNER", "REPO"), tt.state)
if (err != nil) != tt.wantErr {
t.Errorf("RepoMilestones() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !strings.Contains(query, tt.want) {
t.Errorf("query does not contain %v", tt.want)
}
}
}