Make comment command easier to test

This commit is contained in:
Sam Coe 2021-01-05 14:11:26 -08:00
parent de73b16178
commit 155507d31d
No known key found for this signature in database
GPG key ID: 8E322C20F811D086
2 changed files with 76 additions and 82 deletions

View file

@ -13,18 +13,19 @@ import (
"github.com/cli/cli/pkg/cmd/issue/shared"
"github.com/cli/cli/pkg/cmdutil"
"github.com/cli/cli/pkg/iostreams"
"github.com/cli/cli/pkg/prompt"
"github.com/cli/cli/pkg/surveyext"
"github.com/cli/cli/utils"
"github.com/spf13/cobra"
)
type CommentOptions struct {
HttpClient func() (*http.Client, error)
Config func() (config.Config, error)
IO *iostreams.IOStreams
BaseRepo func() (ghrepo.Interface, error)
Edit func(string) (string, error)
HttpClient func() (*http.Client, error)
IO *iostreams.IOStreams
BaseRepo func() (ghrepo.Interface, error)
EditSurvey func() (string, error)
InputTypeSurvey func() (int, error)
ConfirmSubmitSurvey func() (bool, error)
OpenInBrowser func(string) error
SelectorArg string
Interactive bool
@ -40,12 +41,12 @@ const (
func NewCmdComment(f *cmdutil.Factory, runF func(*CommentOptions) error) *cobra.Command {
opts := &CommentOptions{
IO: f.IOStreams,
HttpClient: f.HttpClient,
Config: f.Config,
Edit: func(editorCommand string) (string, error) {
return surveyext.Edit(editorCommand, "*.md", "", f.IOStreams.In, f.IOStreams.Out, f.IOStreams.ErrOut, nil)
},
IO: f.IOStreams,
HttpClient: f.HttpClient,
EditSurvey: editSurvey(f.Config, f.IOStreams),
InputTypeSurvey: inputTypeSurvey,
ConfirmSubmitSurvey: confirmSubmitSurvey,
OpenInBrowser: utils.OpenInBrowser,
}
var webMode bool
@ -96,6 +97,7 @@ func NewCmdComment(f *cmdutil.Factory, runF func(*CommentOptions) error) *cobra.
return commentRun(opts)
},
}
cmd.Flags().StringVarP(&opts.Body, "body", "b", "", "Supply a body. Will prompt for one otherwise.")
cmd.Flags().BoolVarP(&editorMode, "editor", "e", false, "Add body using editor")
cmd.Flags().BoolVarP(&webMode, "web", "w", false, "Add body in browser")
@ -116,7 +118,7 @@ func commentRun(opts *CommentOptions) error {
}
if opts.Interactive {
inputType, err := inputTypeSurvey()
inputType, err := opts.InputTypeSurvey()
if err != nil {
return err
}
@ -129,13 +131,9 @@ func commentRun(opts *CommentOptions) error {
if opts.IO.IsStdoutTTY() {
fmt.Fprintf(opts.IO.ErrOut, "Opening %s in your browser.\n", utils.DisplayURL(openURL))
}
return utils.OpenInBrowser(openURL)
return opts.OpenInBrowser(openURL)
case editor:
editorCommand, err := cmdutil.DetermineEditor(opts.Config)
if err != nil {
return err
}
body, err := opts.Edit(editorCommand)
body, err := opts.EditSurvey()
if err != nil {
return err
}
@ -149,7 +147,7 @@ func commentRun(opts *CommentOptions) error {
}
if opts.Interactive {
cont, err := confirmSubmitSurvey()
cont, err := opts.ConfirmSubmitSurvey()
if err != nil {
return err
}
@ -170,22 +168,32 @@ func commentRun(opts *CommentOptions) error {
return nil
}
func inputTypeSurvey() (int, error) {
var inputTypeSurvey = func() (int, error) {
var inputType int
inputTypeQuestion := &survey.Select{
Message: "Where do you want to draft your comment?",
Options: []string{"Editor", "Web"},
}
err := prompt.SurveyAskOne(inputTypeQuestion, &inputType)
err := survey.AskOne(inputTypeQuestion, &inputType)
return inputType, err
}
func confirmSubmitSurvey() (bool, error) {
var confirmSubmitSurvey = func() (bool, error) {
var confirm bool
submit := &survey.Confirm{
Message: "Submit?",
Default: true,
}
err := prompt.SurveyAskOne(submit, &confirm)
err := survey.AskOne(submit, &confirm)
return confirm, err
}
var editSurvey = func(cf func() (config.Config, error), io *iostreams.IOStreams) func() (string, error) {
return func() (string, error) {
editorCommand, err := cmdutil.DetermineEditor(cf)
if err != nil {
return "", err
}
return surveyext.Edit(editorCommand, "*.md", "", io.In, io.Out, io.ErrOut, nil)
}
}

View file

@ -3,17 +3,12 @@ package comment
import (
"bytes"
"net/http"
"os/exec"
"testing"
"github.com/cli/cli/internal/config"
"github.com/cli/cli/internal/ghrepo"
"github.com/cli/cli/internal/run"
"github.com/cli/cli/pkg/cmdutil"
"github.com/cli/cli/pkg/httpmock"
"github.com/cli/cli/pkg/iostreams"
"github.com/cli/cli/pkg/prompt"
"github.com/cli/cli/test"
"github.com/google/shlex"
"github.com/stretchr/testify/assert"
)
@ -155,69 +150,89 @@ func TestNewCmdComment(t *testing.T) {
func Test_commentRun(t *testing.T) {
tests := []struct {
name string
input *CommentOptions
testInputType int
stdout string
stderr string
wantsErr bool
errMsg string
name string
input *CommentOptions
httpStubs func(*testing.T, *httpmock.Registry)
stdout string
stderr string
}{
{
name: "interactive web",
testInputType: web,
name: "interactive web",
input: &CommentOptions{
SelectorArg: "123",
Interactive: true,
InputType: 0,
Body: "",
InputTypeSurvey: func() (int, error) { return web, nil },
OpenInBrowser: func(string) error { return nil },
},
httpStubs: func(t *testing.T, reg *httpmock.Registry) {
mockIssueFromNumber(t, reg)
},
stderr: "Opening github.com/OWNER/REPO/issues/123 in your browser.\n",
},
{
name: "interactive editor",
testInputType: editor,
name: "interactive editor",
input: &CommentOptions{
SelectorArg: "123",
Interactive: true,
InputType: 0,
Body: "",
Edit: func(string) (string, error) { return "comment body", nil },
EditSurvey: func() (string, error) { return "comment body", nil },
InputTypeSurvey: func() (int, error) { return editor, nil },
ConfirmSubmitSurvey: func() (bool, error) { return true, nil },
},
httpStubs: func(t *testing.T, reg *httpmock.Registry) {
mockIssueFromNumber(t, reg)
mockCommentCreate(t, reg)
},
stdout: "? Body <Received>\nhttps://github.com/OWNER/REPO/issues/123#issuecomment-456\n",
},
{
name: "non-interactive web",
testInputType: web,
name: "non-interactive web",
input: &CommentOptions{
SelectorArg: "123",
Interactive: false,
InputType: web,
Body: "",
OpenInBrowser: func(string) error { return nil },
},
httpStubs: func(t *testing.T, reg *httpmock.Registry) {
mockIssueFromNumber(t, reg)
},
stderr: "Opening github.com/OWNER/REPO/issues/123 in your browser.\n",
},
{
name: "non-interactive editor",
testInputType: editor,
name: "non-interactive editor",
input: &CommentOptions{
SelectorArg: "123",
Interactive: false,
InputType: editor,
Body: "",
Edit: func(string) (string, error) { return "comment body", nil },
EditSurvey: func() (string, error) { return "comment body", nil },
},
httpStubs: func(t *testing.T, reg *httpmock.Registry) {
mockIssueFromNumber(t, reg)
mockCommentCreate(t, reg)
},
stdout: "https://github.com/OWNER/REPO/issues/123#issuecomment-456\n",
},
{
name: "non-interactive inline",
testInputType: inline,
name: "non-interactive inline",
input: &CommentOptions{
SelectorArg: "123",
Interactive: false,
InputType: inline,
Body: "comment body",
},
httpStubs: func(t *testing.T, reg *httpmock.Registry) {
mockIssueFromNumber(t, reg)
mockCommentCreate(t, reg)
},
stdout: "https://github.com/OWNER/REPO/issues/123#issuecomment-456\n",
},
}
@ -227,49 +242,20 @@ func Test_commentRun(t *testing.T) {
io.SetStdinTTY(true)
io.SetStderrTTY(true)
client := &httpmock.Registry{}
defer client.Verify(t)
mockIssueFromNumber(client)
if tt.testInputType != web {
mockCommentCreate(t, client)
}
reg := &httpmock.Registry{}
defer reg.Verify(t)
tt.httpStubs(t, reg)
tt.input.IO = io
tt.input.HttpClient = func() (*http.Client, error) {
return &http.Client{Transport: client}, nil
}
tt.input.Config = func() (config.Config, error) {
return config.NewBlankConfig(), nil
return &http.Client{Transport: reg}, nil
}
tt.input.BaseRepo = func() (ghrepo.Interface, error) {
return ghrepo.New("OWNER", "REPO"), nil
}
if tt.input.Interactive {
as, teardown := prompt.InitAskStubber()
defer teardown()
// Input type select
as.StubOne(tt.testInputType)
if tt.testInputType == editor {
// Confirm submit
as.StubOne(true)
}
}
if tt.testInputType == web {
// Stub browser open
restoreCmd := run.SetPrepareCmd(func(cmd *exec.Cmd) run.Runnable {
return &test.OutputStub{}
})
defer restoreCmd()
}
t.Run(tt.name, func(t *testing.T) {
err := commentRun(tt.input)
if tt.wantsErr {
assert.EqualError(t, err, tt.errMsg)
return
}
assert.NoError(t, err)
assert.Equal(t, tt.stdout, stdout.String())
assert.Equal(t, tt.stderr, stderr.String())
@ -277,7 +263,7 @@ func Test_commentRun(t *testing.T) {
}
}
func mockIssueFromNumber(reg *httpmock.Registry) {
func mockIssueFromNumber(_ *testing.T, reg *httpmock.Registry) {
reg.Register(
httpmock.GraphQL(`query IssueByNumber\b`),
httpmock.StringResponse(`