From bbc3d02cb394c882c9d3bd21bbcf20db509ce973 Mon Sep 17 00:00:00 2001 From: Andy Feller Date: Wed, 30 Jul 2025 09:25:33 -0400 Subject: [PATCH] Refactor tab completion test This commit moves the `gh pr create` tab completion test closer to the logic rather than the commands that use it. This should ensure that any command or flag that lists reviewers will present teams and users as expected. --- pkg/cmd/pr/create/create_test.go | 133 --------------------------- pkg/cmd/pr/shared/completion_test.go | 120 ++++++++++++++++++++++++ 2 files changed, 120 insertions(+), 133 deletions(-) create mode 100644 pkg/cmd/pr/shared/completion_test.go diff --git a/pkg/cmd/pr/create/create_test.go b/pkg/cmd/pr/create/create_test.go index eb39db0f9..9af351830 100644 --- a/pkg/cmd/pr/create/create_test.go +++ b/pkg/cmd/pr/create/create_test.go @@ -2879,136 +2879,3 @@ func TestProjectsV1Deprecation(t *testing.T) { }) }) } - -func Test_requestableReviewersForCompletion(t *testing.T) { - tests := []struct { - name string - tty bool - expectedReviewers []string - httpStubs func(*httpmock.Registry, *testing.T) - }{ - { - name: "when users and teams are both available, both are listed", - expectedReviewers: []string{"MonaLisa\tMona Display Name", "OWNER/core", "OWNER/robots", "hubot"}, - httpStubs: func(reg *httpmock.Registry, t *testing.T) { - reg.Register( - httpmock.GraphQL(`query UserCurrent\b`), - httpmock.StringResponse(`{"data": {"viewer": {"login": "OWNER"} } }`)) - reg.Register( - httpmock.GraphQL(`query RepositoryAssignableUsers\b`), - httpmock.StringResponse(` - { "data": { "repository": { "assignableUsers": { - "nodes": [ - { "login": "hubot", "id": "HUBOTID", "name": "" }, - { "login": "MonaLisa", "id": "MONAID", "name": "Mona Display Name" } - ], - "pageInfo": { "hasNextPage": false } - } } } } - `)) - reg.Register( - httpmock.GraphQL(`query OrganizationTeamList\b`), - httpmock.StringResponse(` - { "data": { "organization": { "teams": { - "nodes": [ - { "slug": "core", "id": "COREID" }, - { "slug": "robots", "id": "ROBOTID" } - ], - "pageInfo": { "hasNextPage": false } - } } } } - `)) - }, - }, - { - name: "when users are available but teams aren't, users are listed", - expectedReviewers: []string{"MonaLisa\tMona Display Name", "hubot"}, - httpStubs: func(reg *httpmock.Registry, t *testing.T) { - reg.Register( - httpmock.GraphQL(`query UserCurrent\b`), - httpmock.StringResponse(`{"data": {"viewer": {"login": "OWNER"} } }`)) - reg.Register( - httpmock.GraphQL(`query RepositoryAssignableUsers\b`), - httpmock.StringResponse(` - { "data": { "repository": { "assignableUsers": { - "nodes": [ - { "login": "hubot", "id": "HUBOTID", "name": "" }, - { "login": "MonaLisa", "id": "MONAID", "name": "Mona Display Name" } - ], - "pageInfo": { "hasNextPage": false } - } } } } - `)) - reg.Register( - httpmock.GraphQL(`query OrganizationTeamList\b`), - httpmock.StringResponse(` - { "data": { "organization": { "teams": { - "nodes": [], - "pageInfo": { "hasNextPage": false } - } } } } - `)) - }, - }, - { - name: "when teams are available but users aren't, teams are listed", - expectedReviewers: []string{"OWNER/core", "OWNER/robots"}, - httpStubs: func(reg *httpmock.Registry, t *testing.T) { - reg.Register( - httpmock.GraphQL(`query UserCurrent\b`), - httpmock.StringResponse(`{"data": {"viewer": {"login": "OWNER"} } }`)) - reg.Register( - httpmock.GraphQL(`query RepositoryAssignableUsers\b`), - httpmock.StringResponse(` - { "data": { "repository": { "assignableUsers": { - "nodes": [], - "pageInfo": { "hasNextPage": false } - } } } } - `)) - reg.Register( - httpmock.GraphQL(`query OrganizationTeamList\b`), - httpmock.StringResponse(` - { "data": { "organization": { "teams": { - "nodes": [ - { "slug": "core", "id": "COREID" }, - { "slug": "robots", "id": "ROBOTID" } - ], - "pageInfo": { "hasNextPage": false } - } } } } - `)) - }, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - reg := &httpmock.Registry{} - defer reg.Verify(t) - if tt.httpStubs != nil { - tt.httpStubs(reg, t) - } - - ios, _, _, _ := iostreams.Test() - ios.SetStdoutTTY(tt.tty) - ios.SetStdinTTY(tt.tty) - ios.SetStderrTTY(tt.tty) - - opts := &CreateOptions{} - opts.IO = ios - opts.HttpClient = func() (*http.Client, error) { - return &http.Client{Transport: reg}, nil - } - opts.Remotes = func() (context.Remotes, error) { - return context.Remotes{ - { - Remote: &git.Remote{ - Name: "origin", - Resolved: "base", - }, - Repo: ghrepo.New("OWNER", "REPO"), - }, - }, nil - } - - reviewers, err := requestableReviewersForCompletion(opts) - require.NoError(t, err) - require.Equal(t, tt.expectedReviewers, reviewers) - }) - } -} diff --git a/pkg/cmd/pr/shared/completion_test.go b/pkg/cmd/pr/shared/completion_test.go new file mode 100644 index 000000000..ca7c3ffa7 --- /dev/null +++ b/pkg/cmd/pr/shared/completion_test.go @@ -0,0 +1,120 @@ +package shared + +import ( + "net/http" + "testing" + + "github.com/cli/cli/v2/internal/ghrepo" + "github.com/cli/cli/v2/pkg/httpmock" + "github.com/stretchr/testify/require" +) + +func TestRequestableReviewersForCompletion(t *testing.T) { + tests := []struct { + name string + expectedReviewers []string + httpStubs func(*httpmock.Registry, *testing.T) + }{ + { + name: "when users and teams are both available, both are listed", + expectedReviewers: []string{"MonaLisa\tMona Display Name", "OWNER/core", "OWNER/robots", "hubot"}, + httpStubs: func(reg *httpmock.Registry, t *testing.T) { + reg.Register( + httpmock.GraphQL(`query UserCurrent\b`), + httpmock.StringResponse(`{"data": {"viewer": {"login": "OWNER"} } }`)) + reg.Register( + httpmock.GraphQL(`query RepositoryAssignableUsers\b`), + httpmock.StringResponse(` + { "data": { "repository": { "assignableUsers": { + "nodes": [ + { "login": "hubot", "id": "HUBOTID", "name": "" }, + { "login": "MonaLisa", "id": "MONAID", "name": "Mona Display Name" } + ], + "pageInfo": { "hasNextPage": false } + } } } } + `)) + reg.Register( + httpmock.GraphQL(`query OrganizationTeamList\b`), + httpmock.StringResponse(` + { "data": { "organization": { "teams": { + "nodes": [ + { "slug": "core", "id": "COREID" }, + { "slug": "robots", "id": "ROBOTID" } + ], + "pageInfo": { "hasNextPage": false } + } } } } + `)) + }, + }, + { + name: "when users are available but teams aren't, users are listed", + expectedReviewers: []string{"MonaLisa\tMona Display Name", "hubot"}, + httpStubs: func(reg *httpmock.Registry, t *testing.T) { + reg.Register( + httpmock.GraphQL(`query UserCurrent\b`), + httpmock.StringResponse(`{"data": {"viewer": {"login": "OWNER"} } }`)) + reg.Register( + httpmock.GraphQL(`query RepositoryAssignableUsers\b`), + httpmock.StringResponse(` + { "data": { "repository": { "assignableUsers": { + "nodes": [ + { "login": "hubot", "id": "HUBOTID", "name": "" }, + { "login": "MonaLisa", "id": "MONAID", "name": "Mona Display Name" } + ], + "pageInfo": { "hasNextPage": false } + } } } } + `)) + reg.Register( + httpmock.GraphQL(`query OrganizationTeamList\b`), + httpmock.StringResponse(` + { "data": { "organization": { "teams": { + "nodes": [], + "pageInfo": { "hasNextPage": false } + } } } } + `)) + }, + }, + { + name: "when teams are available but users aren't, teams are listed", + expectedReviewers: []string{"OWNER/core", "OWNER/robots"}, + httpStubs: func(reg *httpmock.Registry, t *testing.T) { + reg.Register( + httpmock.GraphQL(`query UserCurrent\b`), + httpmock.StringResponse(`{"data": {"viewer": {"login": "OWNER"} } }`)) + reg.Register( + httpmock.GraphQL(`query RepositoryAssignableUsers\b`), + httpmock.StringResponse(` + { "data": { "repository": { "assignableUsers": { + "nodes": [], + "pageInfo": { "hasNextPage": false } + } } } } + `)) + reg.Register( + httpmock.GraphQL(`query OrganizationTeamList\b`), + httpmock.StringResponse(` + { "data": { "organization": { "teams": { + "nodes": [ + { "slug": "core", "id": "COREID" }, + { "slug": "robots", "id": "ROBOTID" } + ], + "pageInfo": { "hasNextPage": false } + } } } } + `)) + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + reg := &httpmock.Registry{} + defer reg.Verify(t) + if tt.httpStubs != nil { + tt.httpStubs(reg, t) + } + + reviewers, err := RequestableReviewersForCompletion(&http.Client{Transport: reg}, ghrepo.New("OWNER", "REPO")) + require.NoError(t, err) + require.Equal(t, tt.expectedReviewers, reviewers) + }) + } +}