github.com/secman-team/gh-api@v1.8.2/api/queries_repo_test.go (about)

     1  package api
     2  
     3  import (
     4  	"io"
     5  	"net/http"
     6  	"strings"
     7  	"testing"
     8  
     9  	"github.com/secman-team/gh-api/internal/ghrepo"
    10  	"github.com/secman-team/gh-api/pkg/httpmock"
    11  )
    12  
    13  func Test_RepoMetadata(t *testing.T) {
    14  	http := &httpmock.Registry{}
    15  	client := NewClient(ReplaceTripper(http))
    16  
    17  	repo, _ := ghrepo.FromFullName("OWNER/REPO")
    18  	input := RepoMetadataInput{
    19  		Assignees:  true,
    20  		Reviewers:  true,
    21  		Labels:     true,
    22  		Projects:   true,
    23  		Milestones: true,
    24  	}
    25  
    26  	http.Register(
    27  		httpmock.GraphQL(`query RepositoryAssignableUsers\b`),
    28  		httpmock.StringResponse(`
    29  		{ "data": { "repository": { "assignableUsers": {
    30  			"nodes": [
    31  				{ "login": "hubot", "id": "HUBOTID" },
    32  				{ "login": "MonaLisa", "id": "MONAID" }
    33  			],
    34  			"pageInfo": { "hasNextPage": false }
    35  		} } } }
    36  		`))
    37  	http.Register(
    38  		httpmock.GraphQL(`query RepositoryLabelList\b`),
    39  		httpmock.StringResponse(`
    40  		{ "data": { "repository": { "labels": {
    41  			"nodes": [
    42  				{ "name": "feature", "id": "FEATUREID" },
    43  				{ "name": "TODO", "id": "TODOID" },
    44  				{ "name": "bug", "id": "BUGID" }
    45  			],
    46  			"pageInfo": { "hasNextPage": false }
    47  		} } } }
    48  		`))
    49  	http.Register(
    50  		httpmock.GraphQL(`query RepositoryMilestoneList\b`),
    51  		httpmock.StringResponse(`
    52  		{ "data": { "repository": { "milestones": {
    53  			"nodes": [
    54  				{ "title": "GA", "id": "GAID" },
    55  				{ "title": "Big One.oh", "id": "BIGONEID" }
    56  			],
    57  			"pageInfo": { "hasNextPage": false }
    58  		} } } }
    59  		`))
    60  	http.Register(
    61  		httpmock.GraphQL(`query RepositoryProjectList\b`),
    62  		httpmock.StringResponse(`
    63  		{ "data": { "repository": { "projects": {
    64  			"nodes": [
    65  				{ "name": "Cleanup", "id": "CLEANUPID" },
    66  				{ "name": "Roadmap", "id": "ROADMAPID" }
    67  			],
    68  			"pageInfo": { "hasNextPage": false }
    69  		} } } }
    70  		`))
    71  	http.Register(
    72  		httpmock.GraphQL(`query OrganizationProjectList\b`),
    73  		httpmock.StringResponse(`
    74  		{ "data": { "organization": { "projects": {
    75  			"nodes": [
    76  				{ "name": "Triage", "id": "TRIAGEID" }
    77  			],
    78  			"pageInfo": { "hasNextPage": false }
    79  		} } } }
    80  		`))
    81  	http.Register(
    82  		httpmock.GraphQL(`query OrganizationTeamList\b`),
    83  		httpmock.StringResponse(`
    84  		{ "data": { "organization": { "teams": {
    85  			"nodes": [
    86  				{ "slug": "owners", "id": "OWNERSID" },
    87  				{ "slug": "Core", "id": "COREID" }
    88  			],
    89  			"pageInfo": { "hasNextPage": false }
    90  		} } } }
    91  		`))
    92  
    93  	result, err := RepoMetadata(client, repo, input)
    94  	if err != nil {
    95  		t.Fatalf("unexpected error: %v", err)
    96  	}
    97  
    98  	expectedMemberIDs := []string{"MONAID", "HUBOTID"}
    99  	memberIDs, err := result.MembersToIDs([]string{"monalisa", "hubot"})
   100  	if err != nil {
   101  		t.Errorf("error resolving members: %v", err)
   102  	}
   103  	if !sliceEqual(memberIDs, expectedMemberIDs) {
   104  		t.Errorf("expected members %v, got %v", expectedMemberIDs, memberIDs)
   105  	}
   106  
   107  	expectedTeamIDs := []string{"COREID", "OWNERSID"}
   108  	teamIDs, err := result.TeamsToIDs([]string{"OWNER/core", "/owners"})
   109  	if err != nil {
   110  		t.Errorf("error resolving teams: %v", err)
   111  	}
   112  	if !sliceEqual(teamIDs, expectedTeamIDs) {
   113  		t.Errorf("expected teams %v, got %v", expectedTeamIDs, teamIDs)
   114  	}
   115  
   116  	expectedLabelIDs := []string{"BUGID", "TODOID"}
   117  	labelIDs, err := result.LabelsToIDs([]string{"bug", "todo"})
   118  	if err != nil {
   119  		t.Errorf("error resolving labels: %v", err)
   120  	}
   121  	if !sliceEqual(labelIDs, expectedLabelIDs) {
   122  		t.Errorf("expected labels %v, got %v", expectedLabelIDs, labelIDs)
   123  	}
   124  
   125  	expectedProjectIDs := []string{"TRIAGEID", "ROADMAPID"}
   126  	projectIDs, err := result.ProjectsToIDs([]string{"triage", "roadmap"})
   127  	if err != nil {
   128  		t.Errorf("error resolving projects: %v", err)
   129  	}
   130  	if !sliceEqual(projectIDs, expectedProjectIDs) {
   131  		t.Errorf("expected projects %v, got %v", expectedProjectIDs, projectIDs)
   132  	}
   133  
   134  	expectedMilestoneID := "BIGONEID"
   135  	milestoneID, err := result.MilestoneToID("big one.oh")
   136  	if err != nil {
   137  		t.Errorf("error resolving milestone: %v", err)
   138  	}
   139  	if milestoneID != expectedMilestoneID {
   140  		t.Errorf("expected milestone %v, got %v", expectedMilestoneID, milestoneID)
   141  	}
   142  }
   143  
   144  func Test_ProjectsToPaths(t *testing.T) {
   145  	expectedProjectPaths := []string{"OWNER/REPO/PROJECT_NUMBER", "ORG/PROJECT_NUMBER"}
   146  	projects := []RepoProject{
   147  		{"id1", "My Project", "/OWNER/REPO/projects/PROJECT_NUMBER"},
   148  		{"id2", "Org Project", "/orgs/ORG/projects/PROJECT_NUMBER"},
   149  		{"id3", "Project", "/orgs/ORG/projects/PROJECT_NUMBER_2"},
   150  	}
   151  	projectNames := []string{"My Project", "Org Project"}
   152  
   153  	projectPaths, err := ProjectsToPaths(projects, projectNames)
   154  	if err != nil {
   155  		t.Errorf("error resolving projects: %v", err)
   156  	}
   157  	if !sliceEqual(projectPaths, expectedProjectPaths) {
   158  		t.Errorf("expected projects %v, got %v", expectedProjectPaths, projectPaths)
   159  	}
   160  }
   161  
   162  func Test_ProjectNamesToPaths(t *testing.T) {
   163  	http := &httpmock.Registry{}
   164  	client := NewClient(ReplaceTripper(http))
   165  
   166  	repo, _ := ghrepo.FromFullName("OWNER/REPO")
   167  
   168  	http.Register(
   169  		httpmock.GraphQL(`query RepositoryProjectList\b`),
   170  		httpmock.StringResponse(`
   171  		{ "data": { "repository": { "projects": {
   172  			"nodes": [
   173  				{ "name": "Cleanup", "id": "CLEANUPID", "resourcePath": "/OWNER/REPO/projects/1" },
   174  				{ "name": "Roadmap", "id": "ROADMAPID", "resourcePath": "/OWNER/REPO/projects/2" }
   175  			],
   176  			"pageInfo": { "hasNextPage": false }
   177  		} } } }
   178  		`))
   179  	http.Register(
   180  		httpmock.GraphQL(`query OrganizationProjectList\b`),
   181  		httpmock.StringResponse(`
   182  			{ "data": { "organization": { "projects": {
   183  				"nodes": [
   184  					{ "name": "Triage", "id": "TRIAGEID", "resourcePath": "/orgs/ORG/projects/1"  }
   185  				],
   186  				"pageInfo": { "hasNextPage": false }
   187  			} } } }
   188  			`))
   189  
   190  	projectPaths, err := ProjectNamesToPaths(client, repo, []string{"Triage", "Roadmap"})
   191  	if err != nil {
   192  		t.Fatalf("unexpected error: %v", err)
   193  	}
   194  
   195  	expectedProjectPaths := []string{"ORG/1", "OWNER/REPO/2"}
   196  	if !sliceEqual(projectPaths, expectedProjectPaths) {
   197  		t.Errorf("expected projects paths %v, got %v", expectedProjectPaths, projectPaths)
   198  	}
   199  }
   200  
   201  func Test_RepoResolveMetadataIDs(t *testing.T) {
   202  	http := &httpmock.Registry{}
   203  	client := NewClient(ReplaceTripper(http))
   204  
   205  	repo, _ := ghrepo.FromFullName("OWNER/REPO")
   206  	input := RepoResolveInput{
   207  		Assignees: []string{"monalisa", "hubot"},
   208  		Reviewers: []string{"monalisa", "octocat", "OWNER/core", "/robots"},
   209  		Labels:    []string{"bug", "help wanted"},
   210  	}
   211  
   212  	expectedQuery := `query RepositoryResolveMetadataIDs {
   213  u000: user(login:"monalisa"){id,login}
   214  u001: user(login:"hubot"){id,login}
   215  u002: user(login:"octocat"){id,login}
   216  repository(owner:"OWNER",name:"REPO"){
   217  l000: label(name:"bug"){id,name}
   218  l001: label(name:"help wanted"){id,name}
   219  }
   220  organization(login:"OWNER"){
   221  t000: team(slug:"core"){id,slug}
   222  t001: team(slug:"robots"){id,slug}
   223  }
   224  }
   225  `
   226  	responseJSON := `
   227  	{ "data": {
   228  		"u000": { "login": "MonaLisa", "id": "MONAID" },
   229  		"u001": { "login": "hubot", "id": "HUBOTID" },
   230  		"u002": { "login": "octocat", "id": "OCTOID" },
   231  		"repository": {
   232  			"l000": { "name": "bug", "id": "BUGID" },
   233  			"l001": { "name": "Help Wanted", "id": "HELPID" }
   234  		},
   235  		"organization": {
   236  			"t000": { "slug": "core", "id": "COREID" },
   237  			"t001": { "slug": "Robots", "id": "ROBOTID" }
   238  		}
   239  	} }
   240  	`
   241  
   242  	http.Register(
   243  		httpmock.GraphQL(`query RepositoryResolveMetadataIDs\b`),
   244  		httpmock.GraphQLQuery(responseJSON, func(q string, _ map[string]interface{}) {
   245  			if q != expectedQuery {
   246  				t.Errorf("expected query %q, got %q", expectedQuery, q)
   247  			}
   248  		}))
   249  
   250  	result, err := RepoResolveMetadataIDs(client, repo, input)
   251  	if err != nil {
   252  		t.Fatalf("unexpected error: %v", err)
   253  	}
   254  
   255  	expectedMemberIDs := []string{"MONAID", "HUBOTID", "OCTOID"}
   256  	memberIDs, err := result.MembersToIDs([]string{"monalisa", "hubot", "octocat"})
   257  	if err != nil {
   258  		t.Errorf("error resolving members: %v", err)
   259  	}
   260  	if !sliceEqual(memberIDs, expectedMemberIDs) {
   261  		t.Errorf("expected members %v, got %v", expectedMemberIDs, memberIDs)
   262  	}
   263  
   264  	expectedTeamIDs := []string{"COREID", "ROBOTID"}
   265  	teamIDs, err := result.TeamsToIDs([]string{"/core", "/robots"})
   266  	if err != nil {
   267  		t.Errorf("error resolving teams: %v", err)
   268  	}
   269  	if !sliceEqual(teamIDs, expectedTeamIDs) {
   270  		t.Errorf("expected members %v, got %v", expectedTeamIDs, teamIDs)
   271  	}
   272  
   273  	expectedLabelIDs := []string{"BUGID", "HELPID"}
   274  	labelIDs, err := result.LabelsToIDs([]string{"bug", "help wanted"})
   275  	if err != nil {
   276  		t.Errorf("error resolving labels: %v", err)
   277  	}
   278  	if !sliceEqual(labelIDs, expectedLabelIDs) {
   279  		t.Errorf("expected members %v, got %v", expectedLabelIDs, labelIDs)
   280  	}
   281  }
   282  
   283  func sliceEqual(a, b []string) bool {
   284  	if len(a) != len(b) {
   285  		return false
   286  	}
   287  
   288  	for i := range a {
   289  		if a[i] != b[i] {
   290  			return false
   291  		}
   292  	}
   293  
   294  	return true
   295  }
   296  
   297  func Test_RepoMilestones(t *testing.T) {
   298  	tests := []struct {
   299  		state   string
   300  		want    string
   301  		wantErr bool
   302  	}{
   303  		{
   304  			state: "open",
   305  			want:  `"states":["OPEN"]`,
   306  		},
   307  		{
   308  			state: "closed",
   309  			want:  `"states":["CLOSED"]`,
   310  		},
   311  		{
   312  			state: "all",
   313  			want:  `"states":["OPEN","CLOSED"]`,
   314  		},
   315  		{
   316  			state:   "invalid state",
   317  			wantErr: true,
   318  		},
   319  	}
   320  	for _, tt := range tests {
   321  		var query string
   322  		reg := &httpmock.Registry{}
   323  		reg.Register(httpmock.MatchAny, func(req *http.Request) (*http.Response, error) {
   324  			buf := new(strings.Builder)
   325  			_, err := io.Copy(buf, req.Body)
   326  			if err != nil {
   327  				return nil, err
   328  			}
   329  			query = buf.String()
   330  			return httpmock.StringResponse("{}")(req)
   331  		})
   332  		client := NewClient(ReplaceTripper(reg))
   333  
   334  		_, err := RepoMilestones(client, ghrepo.New("OWNER", "REPO"), tt.state)
   335  		if (err != nil) != tt.wantErr {
   336  			t.Errorf("RepoMilestones() error = %v, wantErr %v", err, tt.wantErr)
   337  			return
   338  		}
   339  		if !strings.Contains(query, tt.want) {
   340  			t.Errorf("query does not contain %v", tt.want)
   341  		}
   342  	}
   343  }