From be39f4363bfc14078800ebda3d8ddae7e0424ad1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mislav=20Marohni=C4=87?= Date: Thu, 3 Dec 2020 17:47:40 +0100 Subject: [PATCH] Make MetadataSurvey testable by accepting an interface --- pkg/cmd/issue/create/create.go | 8 +- pkg/cmd/pr/create/create.go | 8 +- pkg/cmd/pr/shared/survey.go | 37 +++++--- pkg/cmd/pr/shared/survey_test.go | 144 +++++++++++++++++++++++++++++++ 4 files changed, 184 insertions(+), 13 deletions(-) create mode 100644 pkg/cmd/pr/shared/survey_test.go diff --git a/pkg/cmd/issue/create/create.go b/pkg/cmd/issue/create/create.go index 44cac6ae1..a098b31fa 100644 --- a/pkg/cmd/issue/create/create.go +++ b/pkg/cmd/issue/create/create.go @@ -207,7 +207,13 @@ func createRun(opts *CreateOptions) (err error) { } if action == prShared.MetadataAction { - err = prShared.MetadataSurvey(opts.IO, apiClient, baseRepo, &tb) + fetcher := &prShared.MetadataFetcher{ + IO: opts.IO, + APIClient: apiClient, + Repo: baseRepo, + State: &tb, + } + err = prShared.MetadataSurvey(opts.IO, baseRepo, fetcher, &tb) if err != nil { return } diff --git a/pkg/cmd/pr/create/create.go b/pkg/cmd/pr/create/create.go index 8748582eb..faea5f13d 100644 --- a/pkg/cmd/pr/create/create.go +++ b/pkg/cmd/pr/create/create.go @@ -259,7 +259,13 @@ func createRun(opts *CreateOptions) (err error) { } if action == shared.MetadataAction { - err = shared.MetadataSurvey(opts.IO, client, ctx.BaseRepo, state) + fetcher := &shared.MetadataFetcher{ + IO: opts.IO, + APIClient: client, + Repo: ctx.BaseRepo, + State: state, + } + err = shared.MetadataSurvey(opts.IO, ctx.BaseRepo, fetcher, state) if err != nil { return } diff --git a/pkg/cmd/pr/shared/survey.go b/pkg/cmd/pr/shared/survey.go index 161d662b4..8ef40d047 100644 --- a/pkg/cmd/pr/shared/survey.go +++ b/pkg/cmd/pr/shared/survey.go @@ -12,7 +12,6 @@ import ( "github.com/cli/cli/pkg/iostreams" "github.com/cli/cli/pkg/prompt" "github.com/cli/cli/pkg/surveyext" - "github.com/cli/cli/utils" ) type Action int @@ -196,7 +195,26 @@ func TitleSurvey(state *IssueMetadataState) error { return nil } -func MetadataSurvey(io *iostreams.IOStreams, client *api.Client, baseRepo ghrepo.Interface, state *IssueMetadataState) error { +type MetadataFetcher struct { + IO *iostreams.IOStreams + APIClient *api.Client + Repo ghrepo.Interface + State *IssueMetadataState +} + +func (mf *MetadataFetcher) RepoMetadataFetch(input api.RepoMetadataInput) (*api.RepoMetadataResult, error) { + mf.IO.StartProgressIndicator() + metadataResult, err := api.RepoMetadata(mf.APIClient, mf.Repo, input) + mf.IO.StopProgressIndicator() + mf.State.MetadataResult = metadataResult + return metadataResult, err +} + +type RepoMetadataFetcher interface { + RepoMetadataFetch(api.RepoMetadataInput) (*api.RepoMetadataResult, error) +} + +func MetadataSurvey(io *iostreams.IOStreams, baseRepo ghrepo.Interface, fetcher RepoMetadataFetcher, state *IssueMetadataState) error { isChosen := func(m string) bool { for _, c := range state.Metadata { if m == c { @@ -234,32 +252,29 @@ func MetadataSurvey(io *iostreams.IOStreams, client *api.Client, baseRepo ghrepo Projects: isChosen("Projects"), Milestones: isChosen("Milestone"), } - s := utils.Spinner(io.ErrOut) - utils.StartSpinner(s) - state.MetadataResult, err = api.RepoMetadata(client, baseRepo, metadataInput) - utils.StopSpinner(s) + metadataResult, err := fetcher.RepoMetadataFetch(metadataInput) if err != nil { return fmt.Errorf("error fetching metadata options: %w", err) } var users []string - for _, u := range state.MetadataResult.AssignableUsers { + for _, u := range metadataResult.AssignableUsers { users = append(users, u.Login) } var teams []string - for _, t := range state.MetadataResult.Teams { + for _, t := range metadataResult.Teams { teams = append(teams, fmt.Sprintf("%s/%s", baseRepo.RepoOwner(), t.Slug)) } var labels []string - for _, l := range state.MetadataResult.Labels { + for _, l := range metadataResult.Labels { labels = append(labels, l.Name) } var projects []string - for _, l := range state.MetadataResult.Projects { + for _, l := range metadataResult.Projects { projects = append(projects, l.Name) } milestones := []string{noMilestone} - for _, m := range state.MetadataResult.Milestones { + for _, m := range metadataResult.Milestones { milestones = append(milestones, m.Title) } diff --git a/pkg/cmd/pr/shared/survey_test.go b/pkg/cmd/pr/shared/survey_test.go new file mode 100644 index 000000000..a500040d3 --- /dev/null +++ b/pkg/cmd/pr/shared/survey_test.go @@ -0,0 +1,144 @@ +package shared + +import ( + "testing" + + "github.com/cli/cli/api" + "github.com/cli/cli/internal/ghrepo" + "github.com/cli/cli/pkg/iostreams" + "github.com/cli/cli/pkg/prompt" + "github.com/stretchr/testify/assert" +) + +type metadataFetcher struct { + metadataResult *api.RepoMetadataResult +} + +func (mf *metadataFetcher) RepoMetadataFetch(input api.RepoMetadataInput) (*api.RepoMetadataResult, error) { + return mf.metadataResult, nil +} + +func TestMetadataSurvey_selectAll(t *testing.T) { + io, _, stdout, stderr := iostreams.Test() + + repo := ghrepo.New("OWNER", "REPO") + + fetcher := &metadataFetcher{ + metadataResult: &api.RepoMetadataResult{ + AssignableUsers: []api.RepoAssignee{ + {Login: "hubot"}, + {Login: "monalisa"}, + }, + Labels: []api.RepoLabel{ + {Name: "help wanted"}, + {Name: "good first issue"}, + }, + Projects: []api.RepoProject{ + {Name: "Huge Refactoring"}, + {Name: "The road to 1.0"}, + }, + Milestones: []api.RepoMilestone{ + {Title: "1.2 patch release"}, + }, + }, + } + + as, restoreAsk := prompt.InitAskStubber() + defer restoreAsk() + + as.Stub([]*prompt.QuestionStub{ + { + Name: "metadata", + Value: []string{"Labels", "Projects", "Assignees", "Reviewers", "Milestone"}, + }, + }) + as.Stub([]*prompt.QuestionStub{ + { + Name: "reviewers", + Value: []string{"monalisa"}, + }, + { + Name: "assignees", + Value: []string{"hubot"}, + }, + { + Name: "labels", + Value: []string{"good first issue"}, + }, + { + Name: "projects", + Value: []string{"The road to 1.0"}, + }, + { + Name: "milestone", + Value: []string{"(none)"}, + }, + }) + + state := &IssueMetadataState{ + Assignees: []string{"hubot"}, + } + err := MetadataSurvey(io, repo, fetcher, state) + assert.NoError(t, err) + + assert.Equal(t, "", stdout.String()) + assert.Equal(t, "", stderr.String()) + + assert.Equal(t, []string{"hubot"}, state.Assignees) + assert.Equal(t, []string{"monalisa"}, state.Reviewers) + assert.Equal(t, []string{"good first issue"}, state.Labels) + assert.Equal(t, []string{"The road to 1.0"}, state.Projects) + assert.Equal(t, []string{}, state.Milestones) +} + +func TestMetadataSurvey_keepExisting(t *testing.T) { + io, _, stdout, stderr := iostreams.Test() + + repo := ghrepo.New("OWNER", "REPO") + + fetcher := &metadataFetcher{ + metadataResult: &api.RepoMetadataResult{ + Labels: []api.RepoLabel{ + {Name: "help wanted"}, + {Name: "good first issue"}, + }, + Projects: []api.RepoProject{ + {Name: "Huge Refactoring"}, + {Name: "The road to 1.0"}, + }, + }, + } + + as, restoreAsk := prompt.InitAskStubber() + defer restoreAsk() + + as.Stub([]*prompt.QuestionStub{ + { + Name: "metadata", + Value: []string{"Labels", "Projects"}, + }, + }) + as.Stub([]*prompt.QuestionStub{ + { + Name: "labels", + Value: []string{"good first issue"}, + }, + { + Name: "projects", + Value: []string{"The road to 1.0"}, + }, + }) + + state := &IssueMetadataState{ + Assignees: []string{"hubot"}, + } + err := MetadataSurvey(io, repo, fetcher, state) + assert.NoError(t, err) + + assert.Equal(t, "", stdout.String()) + assert.Equal(t, "", stderr.String()) + + assert.Equal(t, []string{"hubot"}, state.Assignees) + assert.Equal(t, []string{"good first issue"}, state.Labels) + assert.Equal(t, []string{"The road to 1.0"}, state.Projects) +}