use Prompter in pr create
Note that this isn't done; it's leaving the metadata piece alone until better testing utils are in place
This commit is contained in:
parent
57fbe4f317
commit
a3b1bb7fb2
5 changed files with 208 additions and 148 deletions
|
|
@ -23,6 +23,7 @@ type CreateOptions struct {
|
|||
IO *iostreams.IOStreams
|
||||
BaseRepo func() (ghrepo.Interface, error)
|
||||
Browser browser.Browser
|
||||
Prompter prShared.Prompt
|
||||
|
||||
RootDirOverride string
|
||||
|
||||
|
|
@ -46,6 +47,7 @@ func NewCmdCreate(f *cmdutil.Factory, runF func(*CreateOptions) error) *cobra.Co
|
|||
HttpClient: f.HttpClient,
|
||||
Config: f.Config,
|
||||
Browser: f.Browser,
|
||||
Prompter: f.Prompter,
|
||||
}
|
||||
|
||||
var bodyFile string
|
||||
|
|
@ -194,16 +196,10 @@ func createRun(opts *CreateOptions) (err error) {
|
|||
var openURL string
|
||||
|
||||
if opts.Interactive {
|
||||
var editorCommand string
|
||||
editorCommand, err = cmdutil.DetermineEditor(opts.Config)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
defer prShared.PreserveInput(opts.IO, &tb, &err)()
|
||||
|
||||
if opts.Title == "" {
|
||||
err = prShared.TitleSurvey(&tb)
|
||||
err = prShared.TitleSurvey(opts.Prompter, &tb)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
|
@ -227,7 +223,7 @@ func createRun(opts *CreateOptions) (err error) {
|
|||
}
|
||||
}
|
||||
|
||||
err = prShared.BodySurvey(&tb, templateContent, editorCommand)
|
||||
err = prShared.BodySurvey(opts.Prompter, &tb, templateContent)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
|
@ -239,7 +235,7 @@ func createRun(opts *CreateOptions) (err error) {
|
|||
}
|
||||
|
||||
allowPreview := !tb.HasMetadata() && prShared.ValidURL(openURL)
|
||||
action, err = prShared.ConfirmIssueSubmission(allowPreview, repo.ViewerCanTriage())
|
||||
action, err = prShared.ConfirmIssueSubmission(opts.Prompter, allowPreview, repo.ViewerCanTriage())
|
||||
if err != nil {
|
||||
err = fmt.Errorf("unable to confirm: %w", err)
|
||||
return
|
||||
|
|
@ -257,7 +253,7 @@ func createRun(opts *CreateOptions) (err error) {
|
|||
return
|
||||
}
|
||||
|
||||
action, err = prShared.ConfirmIssueSubmission(!tb.HasMetadata(), false)
|
||||
action, err = prShared.ConfirmIssueSubmission(opts.Prompter, !tb.HasMetadata(), false)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import (
|
|||
"github.com/cli/cli/v2/internal/browser"
|
||||
"github.com/cli/cli/v2/internal/config"
|
||||
"github.com/cli/cli/v2/internal/ghrepo"
|
||||
"github.com/cli/cli/v2/internal/prompter"
|
||||
"github.com/cli/cli/v2/internal/run"
|
||||
prShared "github.com/cli/cli/v2/pkg/cmd/pr/shared"
|
||||
"github.com/cli/cli/v2/pkg/cmdutil"
|
||||
|
|
@ -288,11 +289,11 @@ func Test_createRun(t *testing.T) {
|
|||
|
||||
/*** LEGACY TESTS ***/
|
||||
|
||||
func runCommand(rt http.RoundTripper, isTTY bool, cli string) (*test.CmdOut, error) {
|
||||
return runCommandWithRootDirOverridden(rt, isTTY, cli, "")
|
||||
func runCommand(rt http.RoundTripper, isTTY bool, cli string, pm *prompter.PrompterMock) (*test.CmdOut, error) {
|
||||
return runCommandWithRootDirOverridden(rt, isTTY, cli, "", pm)
|
||||
}
|
||||
|
||||
func runCommandWithRootDirOverridden(rt http.RoundTripper, isTTY bool, cli string, rootDir string) (*test.CmdOut, error) {
|
||||
func runCommandWithRootDirOverridden(rt http.RoundTripper, isTTY bool, cli string, rootDir string, pm *prompter.PrompterMock) (*test.CmdOut, error) {
|
||||
ios, _, stdout, stderr := iostreams.Test()
|
||||
ios.SetStdoutTTY(isTTY)
|
||||
ios.SetStdinTTY(isTTY)
|
||||
|
|
@ -310,7 +311,8 @@ func runCommandWithRootDirOverridden(rt http.RoundTripper, isTTY bool, cli strin
|
|||
BaseRepo: func() (ghrepo.Interface, error) {
|
||||
return ghrepo.New("OWNER", "REPO"), nil
|
||||
},
|
||||
Browser: browser,
|
||||
Browser: browser,
|
||||
Prompter: pm,
|
||||
}
|
||||
|
||||
cmd := NewCmdCreate(factory, func(opts *CreateOptions) error {
|
||||
|
|
@ -361,7 +363,7 @@ func TestIssueCreate(t *testing.T) {
|
|||
}),
|
||||
)
|
||||
|
||||
output, err := runCommand(http, true, `-t hello -b "cash rules everything around me"`)
|
||||
output, err := runCommand(http, true, `-t hello -b "cash rules everything around me"`, nil)
|
||||
if err != nil {
|
||||
t.Errorf("error running command `issue create`: %v", err)
|
||||
}
|
||||
|
|
@ -403,12 +405,28 @@ func TestIssueCreate_recover(t *testing.T) {
|
|||
assert.Equal(t, []interface{}{"BUGID", "TODOID"}, inputs["labelIds"])
|
||||
}))
|
||||
|
||||
//nolint:staticcheck // SA1019: prompt.NewAskStubber is deprecated: use PrompterMock
|
||||
as := prompt.NewAskStubber(t)
|
||||
|
||||
as.StubPrompt("Title").AnswerDefault()
|
||||
as.StubPrompt("Body").AnswerDefault()
|
||||
as.StubPrompt("What's next?").AnswerWith("Submit")
|
||||
pm := &prompter.PrompterMock{}
|
||||
pm.InputFunc = func(p, d string) (string, error) {
|
||||
if p == "Title" {
|
||||
return d, nil
|
||||
} else {
|
||||
return "", prompter.NoSuchPromptErr(p)
|
||||
}
|
||||
}
|
||||
pm.MarkdownEditorFunc = func(p, d string, ba bool) (string, error) {
|
||||
if p == "Body" {
|
||||
return d, nil
|
||||
} else {
|
||||
return "", prompter.NoSuchPromptErr(p)
|
||||
}
|
||||
}
|
||||
pm.SelectFunc = func(p, _ string, opts []string) (int, error) {
|
||||
if p == "What's next?" {
|
||||
return prompter.IndexFor(opts, "Submit")
|
||||
} else {
|
||||
return -1, prompter.NoSuchPromptErr(p)
|
||||
}
|
||||
}
|
||||
|
||||
tmpfile, err := os.CreateTemp(t.TempDir(), "testrecover*")
|
||||
assert.NoError(t, err)
|
||||
|
|
@ -428,7 +446,7 @@ func TestIssueCreate_recover(t *testing.T) {
|
|||
|
||||
args := fmt.Sprintf("--recover '%s'", tmpfile.Name())
|
||||
|
||||
output, err := runCommandWithRootDirOverridden(http, true, args, "")
|
||||
output, err := runCommandWithRootDirOverridden(http, true, args, "", pm)
|
||||
if err != nil {
|
||||
t.Errorf("error running command `issue create`: %v", err)
|
||||
}
|
||||
|
|
@ -474,13 +492,26 @@ func TestIssueCreate_nonLegacyTemplate(t *testing.T) {
|
|||
//nolint:staticcheck // SA1019: prompt.NewAskStubber is deprecated: use PrompterMock
|
||||
as := prompt.NewAskStubber(t)
|
||||
|
||||
// TODO fix
|
||||
as.StubPrompt("Choose a template").AnswerWith("Submit a request")
|
||||
as.StubPrompt("Body").AnswerDefault()
|
||||
as.StubPrompt("What's next?").
|
||||
AssertOptions([]string{"Submit", "Continue in browser", "Cancel"}).
|
||||
AnswerWith("Submit")
|
||||
|
||||
output, err := runCommandWithRootDirOverridden(http, true, `-t hello`, "./fixtures/repoWithNonLegacyIssueTemplates")
|
||||
pm := &prompter.PrompterMock{}
|
||||
pm.MarkdownEditorFunc = func(p, d string, ba bool) (string, error) {
|
||||
if p == "Body" {
|
||||
return d, nil
|
||||
} else {
|
||||
return "", prompter.NoSuchPromptErr(p)
|
||||
}
|
||||
}
|
||||
pm.SelectFunc = func(p, _ string, opts []string) (int, error) {
|
||||
if p == "What's next?" {
|
||||
return prompter.IndexFor(opts, "Submit")
|
||||
} else {
|
||||
return -1, prompter.NoSuchPromptErr(p)
|
||||
}
|
||||
}
|
||||
|
||||
output, err := runCommandWithRootDirOverridden(http, true, `-t hello`, "./fixtures/repoWithNonLegacyIssueTemplates", pm)
|
||||
if err != nil {
|
||||
t.Errorf("error running command `issue create`: %v", err)
|
||||
}
|
||||
|
|
@ -502,16 +533,26 @@ func TestIssueCreate_continueInBrowser(t *testing.T) {
|
|||
} } }`),
|
||||
)
|
||||
|
||||
//nolint:staticcheck // SA1019: prompt.NewAskStubber is deprecated: use PrompterMock
|
||||
as := prompt.NewAskStubber(t)
|
||||
|
||||
as.StubPrompt("Title").AnswerWith("hello")
|
||||
as.StubPrompt("What's next?").AnswerWith("Continue in browser")
|
||||
pm := &prompter.PrompterMock{}
|
||||
pm.InputFunc = func(p, d string) (string, error) {
|
||||
if p == "Title" {
|
||||
return "hello", nil
|
||||
} else {
|
||||
return "", prompter.NoSuchPromptErr(p)
|
||||
}
|
||||
}
|
||||
pm.SelectFunc = func(p, _ string, opts []string) (int, error) {
|
||||
if p == "What's next?" {
|
||||
return prompter.IndexFor(opts, "Continue in browser")
|
||||
} else {
|
||||
return -1, prompter.NoSuchPromptErr(p)
|
||||
}
|
||||
}
|
||||
|
||||
_, cmdTeardown := run.Stub()
|
||||
defer cmdTeardown(t)
|
||||
|
||||
output, err := runCommand(http, true, `-b body`)
|
||||
output, err := runCommand(http, true, `-b body`, pm)
|
||||
if err != nil {
|
||||
t.Errorf("error running command `issue create`: %v", err)
|
||||
}
|
||||
|
|
@ -596,7 +637,7 @@ func TestIssueCreate_metadata(t *testing.T) {
|
|||
}
|
||||
}))
|
||||
|
||||
output, err := runCommand(http, true, `-t TITLE -b BODY -a monalisa -l bug -l todo -p roadmap -m 'big one.oh'`)
|
||||
output, err := runCommand(http, true, `-t TITLE -b BODY -a monalisa -l bug -l todo -p roadmap -m 'big one.oh'`, nil)
|
||||
if err != nil {
|
||||
t.Errorf("error running command `issue create`: %v", err)
|
||||
}
|
||||
|
|
@ -617,7 +658,7 @@ func TestIssueCreate_disabledIssues(t *testing.T) {
|
|||
} } }`),
|
||||
)
|
||||
|
||||
_, err := runCommand(http, true, `-t heres -b johnny`)
|
||||
_, err := runCommand(http, true, `-t heres -b johnny`, nil)
|
||||
if err == nil || err.Error() != "the 'OWNER/REPO' repository has disabled issues" {
|
||||
t.Errorf("error running command `issue create`: %v", err)
|
||||
}
|
||||
|
|
@ -668,7 +709,7 @@ func TestIssueCreate_AtMeAssignee(t *testing.T) {
|
|||
assert.Equal(t, []interface{}{"MONAID", "SOMEID"}, inputs["assigneeIds"])
|
||||
}))
|
||||
|
||||
output, err := runCommand(http, true, `-a @me -a someoneelse -t hello -b "cash rules everything around me"`)
|
||||
output, err := runCommand(http, true, `-a @me -a someoneelse -t hello -b "cash rules everything around me"`, nil)
|
||||
if err != nil {
|
||||
t.Errorf("error running command `issue create`: %v", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/AlecAivazis/survey/v2"
|
||||
"github.com/MakeNowJust/heredoc"
|
||||
"github.com/cli/cli/v2/api"
|
||||
ghContext "github.com/cli/cli/v2/context"
|
||||
|
|
@ -22,14 +21,9 @@ import (
|
|||
"github.com/cli/cli/v2/pkg/cmd/pr/shared"
|
||||
"github.com/cli/cli/v2/pkg/cmdutil"
|
||||
"github.com/cli/cli/v2/pkg/iostreams"
|
||||
"github.com/cli/cli/v2/pkg/prompt"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
type iprompter interface {
|
||||
Select(string, string, []string) (int, error)
|
||||
}
|
||||
|
||||
type CreateOptions struct {
|
||||
// This struct stores user input and factory functions
|
||||
HttpClient func() (*http.Client, error)
|
||||
|
|
@ -39,7 +33,7 @@ type CreateOptions struct {
|
|||
Remotes func() (ghContext.Remotes, error)
|
||||
Branch func() (string, error)
|
||||
Browser browser.Browser
|
||||
Prompter iprompter
|
||||
Prompter shared.Prompt
|
||||
Finder shared.PRFinder
|
||||
|
||||
TitleProvided bool
|
||||
|
|
@ -276,17 +270,12 @@ func createRun(opts *CreateOptions) (err error) {
|
|||
}
|
||||
|
||||
if !opts.TitleProvided {
|
||||
err = shared.TitleSurvey(state)
|
||||
err = shared.TitleSurvey(opts.Prompter, state)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
editorCommand, err := cmdutil.DetermineEditor(opts.Config)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
defer shared.PreserveInput(opts.IO, state, &err)()
|
||||
|
||||
if !opts.BodyProvided {
|
||||
|
|
@ -306,7 +295,7 @@ func createRun(opts *CreateOptions) (err error) {
|
|||
}
|
||||
}
|
||||
|
||||
err = shared.BodySurvey(state, templateContent, editorCommand)
|
||||
err = shared.BodySurvey(opts.Prompter, state, templateContent)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
|
@ -319,7 +308,7 @@ func createRun(opts *CreateOptions) (err error) {
|
|||
|
||||
allowPreview := !state.HasMetadata() && shared.ValidURL(openURL)
|
||||
allowMetadata := ctx.BaseRepo.ViewerCanTriage()
|
||||
action, err := shared.ConfirmPRSubmission(allowPreview, allowMetadata, state.Draft)
|
||||
action, err := shared.ConfirmPRSubmission(opts.Prompter, allowPreview, allowMetadata, state.Draft)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to confirm: %w", err)
|
||||
}
|
||||
|
|
@ -336,7 +325,7 @@ func createRun(opts *CreateOptions) (err error) {
|
|||
return
|
||||
}
|
||||
|
||||
action, err = shared.ConfirmPRSubmission(!state.HasMetadata(), false, state.Draft)
|
||||
action, err = shared.ConfirmPRSubmission(opts.Prompter, !state.HasMetadata(), false, state.Draft)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
|
@ -577,12 +566,7 @@ func NewCreateContext(opts *CreateOptions) (*CreateContext, error) {
|
|||
pushOptions = append(pushOptions, "Skip pushing the branch")
|
||||
pushOptions = append(pushOptions, "Cancel")
|
||||
|
||||
var selectedOption int
|
||||
//nolint:staticcheck // SA1019: prompt.SurveyAskOne is deprecated: use Prompter
|
||||
err = prompt.SurveyAskOne(&survey.Select{
|
||||
Message: fmt.Sprintf("Where should we push the '%s' branch?", headBranch),
|
||||
Options: pushOptions,
|
||||
}, &selectedOption)
|
||||
selectedOption, err := opts.Prompter.Select(fmt.Sprintf("Where should we push the '%s' branch?", headBranch), "", pushOptions)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import (
|
|||
"github.com/cli/cli/v2/internal/browser"
|
||||
"github.com/cli/cli/v2/internal/config"
|
||||
"github.com/cli/cli/v2/internal/ghrepo"
|
||||
"github.com/cli/cli/v2/internal/prompter"
|
||||
"github.com/cli/cli/v2/internal/run"
|
||||
"github.com/cli/cli/v2/pkg/cmd/pr/shared"
|
||||
prShared "github.com/cli/cli/v2/pkg/cmd/pr/shared"
|
||||
|
|
@ -188,6 +189,7 @@ func Test_createRun(t *testing.T) {
|
|||
setup func(*CreateOptions, *testing.T) func()
|
||||
cmdStubs func(*run.CommandStubber)
|
||||
askStubs func(*prompt.AskStubber) // TODO eventually migrate to PrompterMock
|
||||
promptStubs func(*prompter.PrompterMock)
|
||||
httpStubs func(*httpmock.Registry, *testing.T)
|
||||
expectedOut string
|
||||
expectedErrOut string
|
||||
|
|
@ -268,8 +270,14 @@ func Test_createRun(t *testing.T) {
|
|||
cs.Register(`git show-ref --verify -- HEAD refs/remotes/origin/feature`, 0, "")
|
||||
cs.Register(`git push --set-upstream origin HEAD:feature`, 0, "")
|
||||
},
|
||||
askStubs: func(as *prompt.AskStubber) {
|
||||
as.StubPrompt("Where should we push the 'feature' branch?").AnswerDefault()
|
||||
promptStubs: func(pm *prompter.PrompterMock) {
|
||||
pm.SelectFunc = func(p, _ string, opts []string) (int, error) {
|
||||
if p == "Where should we push the 'feature' branch?" {
|
||||
return 0, nil
|
||||
} else {
|
||||
return -1, prompter.NoSuchPromptErr(p)
|
||||
}
|
||||
}
|
||||
},
|
||||
expectedOut: "https://github.com/OWNER/REPO/pull/12\n",
|
||||
expectedErrOut: "\nCreating pull request for feature into master in OWNER/REPO\n\n",
|
||||
|
|
@ -309,8 +317,14 @@ func Test_createRun(t *testing.T) {
|
|||
cs.Register(`git show-ref --verify -- HEAD refs/remotes/origin/feature`, 0, "")
|
||||
cs.Register(`git push --set-upstream origin HEAD:feature`, 0, "")
|
||||
},
|
||||
askStubs: func(as *prompt.AskStubber) {
|
||||
as.StubPrompt("Where should we push the 'feature' branch?").AnswerDefault()
|
||||
promptStubs: func(pm *prompter.PrompterMock) {
|
||||
pm.SelectFunc = func(p, _ string, opts []string) (int, error) {
|
||||
if p == "Where should we push the 'feature' branch?" {
|
||||
return 0, nil
|
||||
} else {
|
||||
return -1, prompter.NoSuchPromptErr(p)
|
||||
}
|
||||
}
|
||||
},
|
||||
expectedOut: "https://github.com/OWNER/REPO/pull/12\n",
|
||||
expectedErrOut: "\nCreating pull request for feature into master in OWNER/REPO\n\n",
|
||||
|
|
@ -354,10 +368,14 @@ func Test_createRun(t *testing.T) {
|
|||
cs.Register(`git remote add -f fork https://github.com/monalisa/REPO.git`, 0, "")
|
||||
cs.Register(`git push --set-upstream fork HEAD:feature`, 0, "")
|
||||
},
|
||||
askStubs: func(as *prompt.AskStubber) {
|
||||
as.StubPrompt("Where should we push the 'feature' branch?").
|
||||
AssertOptions([]string{"OWNER/REPO", "Create a fork of OWNER/REPO", "Skip pushing the branch", "Cancel"}).
|
||||
AnswerWith("Create a fork of OWNER/REPO")
|
||||
promptStubs: func(pm *prompter.PrompterMock) {
|
||||
pm.SelectFunc = func(p, _ string, opts []string) (int, error) {
|
||||
if p == "Where should we push the 'feature' branch?" {
|
||||
return prompter.IndexFor(opts, "Create a fork of OWNER/REPO")
|
||||
} else {
|
||||
return -1, prompter.NoSuchPromptErr(p)
|
||||
}
|
||||
}
|
||||
},
|
||||
expectedOut: "https://github.com/OWNER/REPO/pull/12\n",
|
||||
expectedErrOut: "\nCreating pull request for monalisa:feature into master in OWNER/REPO\n\n",
|
||||
|
|
@ -486,10 +504,22 @@ func Test_createRun(t *testing.T) {
|
|||
as.StubPrompt("Choose a template").
|
||||
AssertOptions([]string{"template1", "template2", "Open a blank pull request"}).
|
||||
AnswerWith("template1")
|
||||
as.StubPrompt("Body").AnswerDefault()
|
||||
as.StubPrompt("What's next?").
|
||||
AssertOptions([]string{"Submit", "Submit as draft", "Continue in browser", "Add metadata", "Cancel"}).
|
||||
AnswerDefault()
|
||||
},
|
||||
promptStubs: func(pm *prompter.PrompterMock) {
|
||||
pm.MarkdownEditorFunc = func(p, d string, ba bool) (string, error) {
|
||||
if p == "Body" {
|
||||
return d, nil
|
||||
} else {
|
||||
return "", prompter.NoSuchPromptErr(p)
|
||||
}
|
||||
}
|
||||
pm.SelectFunc = func(p, _ string, opts []string) (int, error) {
|
||||
if p == "What's next?" {
|
||||
return 0, nil
|
||||
} else {
|
||||
return -1, prompter.NoSuchPromptErr(p)
|
||||
}
|
||||
}
|
||||
},
|
||||
expectedOut: "https://github.com/OWNER/REPO/pull/12\n",
|
||||
expectedErrOut: "\nCreating pull request for feature into master in OWNER/REPO\n\n",
|
||||
|
|
@ -636,10 +666,14 @@ func Test_createRun(t *testing.T) {
|
|||
cs.Register(`git( .+)? log( .+)? origin/master\.\.\.feature`, 0, "")
|
||||
cs.Register(`git push --set-upstream origin HEAD:feature`, 0, "")
|
||||
},
|
||||
askStubs: func(as *prompt.AskStubber) {
|
||||
as.StubPrompt("Where should we push the 'feature' branch?").
|
||||
AssertOptions([]string{"OWNER/REPO", "Skip pushing the branch", "Cancel"}).
|
||||
AnswerDefault()
|
||||
promptStubs: func(pm *prompter.PrompterMock) {
|
||||
pm.SelectFunc = func(p, _ string, opts []string) (int, error) {
|
||||
if p == "Where should we push the 'feature' branch?" {
|
||||
return 0, nil
|
||||
} else {
|
||||
return -1, prompter.NoSuchPromptErr(p)
|
||||
}
|
||||
}
|
||||
},
|
||||
expectedErrOut: "Opening github.com/OWNER/REPO/compare/master...feature in your browser.\n",
|
||||
expectedBrowse: "https://github.com/OWNER/REPO/compare/master...feature?body=&expand=1",
|
||||
|
|
@ -685,8 +719,14 @@ func Test_createRun(t *testing.T) {
|
|||
cs.Register(`git push --set-upstream origin HEAD:feature`, 0, "")
|
||||
|
||||
},
|
||||
askStubs: func(as *prompt.AskStubber) {
|
||||
as.StubPrompt("Where should we push the 'feature' branch?").AnswerDefault()
|
||||
promptStubs: func(pm *prompter.PrompterMock) {
|
||||
pm.SelectFunc = func(p, _ string, opts []string) (int, error) {
|
||||
if p == "Where should we push the 'feature' branch?" {
|
||||
return 0, nil
|
||||
} else {
|
||||
return -1, prompter.NoSuchPromptErr(p)
|
||||
}
|
||||
}
|
||||
},
|
||||
expectedErrOut: "Opening github.com/OWNER/REPO/compare/master...feature in your browser.\n",
|
||||
expectedBrowse: "https://github.com/OWNER/REPO/compare/master...feature?body=&expand=1&projects=ORG%2F1",
|
||||
|
|
@ -727,10 +767,22 @@ func Test_createRun(t *testing.T) {
|
|||
},
|
||||
askStubs: func(as *prompt.AskStubber) {
|
||||
as.StubPrompt("Choose a template").AnswerDefault()
|
||||
as.StubPrompt("Body").AnswerDefault()
|
||||
as.StubPrompt("What's next?").
|
||||
AssertOptions([]string{"Submit", "Submit as draft", "Continue in browser", "Add metadata", "Cancel"}).
|
||||
AnswerWith("Submit as draft")
|
||||
},
|
||||
promptStubs: func(pm *prompter.PrompterMock) {
|
||||
pm.MarkdownEditorFunc = func(p, d string, ba bool) (string, error) {
|
||||
if p == "Body" {
|
||||
return d, nil
|
||||
} else {
|
||||
return "", prompter.NoSuchPromptErr(p)
|
||||
}
|
||||
}
|
||||
pm.SelectFunc = func(p, _ string, opts []string) (int, error) {
|
||||
if p == "What's next?" {
|
||||
return prompter.IndexFor(opts, "Submit as draft")
|
||||
} else {
|
||||
return -1, prompter.NoSuchPromptErr(p)
|
||||
}
|
||||
}
|
||||
},
|
||||
expectedOut: "https://github.com/OWNER/REPO/pull/12\n",
|
||||
expectedErrOut: "\nCreating pull request for feature into master in OWNER/REPO\n\n",
|
||||
|
|
@ -771,10 +823,28 @@ func Test_createRun(t *testing.T) {
|
|||
cmdStubs: func(cs *run.CommandStubber) {
|
||||
cs.Register(`git( .+)? log( .+)? origin/master\.\.\.feature`, 0, "")
|
||||
},
|
||||
askStubs: func(as *prompt.AskStubber) {
|
||||
as.StubPrompt("Title").AnswerDefault()
|
||||
as.StubPrompt("Body").AnswerDefault()
|
||||
as.StubPrompt("What's next?").AnswerDefault()
|
||||
promptStubs: func(pm *prompter.PrompterMock) {
|
||||
pm.InputFunc = func(p, d string) (string, error) {
|
||||
if p == "Title" {
|
||||
return d, nil
|
||||
} else {
|
||||
return "", prompter.NoSuchPromptErr(p)
|
||||
}
|
||||
}
|
||||
pm.MarkdownEditorFunc = func(p, d string, ba bool) (string, error) {
|
||||
if p == "Body" {
|
||||
return d, nil
|
||||
} else {
|
||||
return "", prompter.NoSuchPromptErr(p)
|
||||
}
|
||||
}
|
||||
pm.SelectFunc = func(p, _ string, opts []string) (int, error) {
|
||||
if p == "What's next?" {
|
||||
return 0, nil
|
||||
} else {
|
||||
return -1, prompter.NoSuchPromptErr(p)
|
||||
}
|
||||
}
|
||||
},
|
||||
setup: func(opts *CreateOptions, t *testing.T) func() {
|
||||
tmpfile, err := os.CreateTemp(t.TempDir(), "testrecover*")
|
||||
|
|
@ -830,6 +900,12 @@ func Test_createRun(t *testing.T) {
|
|||
tt.askStubs(ask)
|
||||
}
|
||||
|
||||
pm := &prompter.PrompterMock{}
|
||||
|
||||
if tt.promptStubs != nil {
|
||||
tt.promptStubs(pm)
|
||||
}
|
||||
|
||||
cs, cmdTeardown := run.Stub()
|
||||
defer cmdTeardown(t)
|
||||
cs.Register(`git status --porcelain`, 0, "")
|
||||
|
|
@ -839,6 +915,7 @@ func Test_createRun(t *testing.T) {
|
|||
}
|
||||
|
||||
opts := CreateOptions{}
|
||||
opts.Prompter = pm
|
||||
|
||||
ios, _, stdout, stderr := iostreams.Test()
|
||||
// TODO do i need to bother with this
|
||||
|
|
@ -1064,3 +1141,5 @@ func Test_generateCompareURL(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TODO interactive metadata tests once: 1) we have test utils for Prompter and 2) metadata questions use Prompter
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ import (
|
|||
"github.com/cli/cli/v2/internal/ghrepo"
|
||||
"github.com/cli/cli/v2/pkg/iostreams"
|
||||
"github.com/cli/cli/v2/pkg/prompt"
|
||||
"github.com/cli/cli/v2/pkg/surveyext"
|
||||
)
|
||||
|
||||
type Action int
|
||||
|
|
@ -32,15 +31,21 @@ const (
|
|||
cancelLabel = "Cancel"
|
||||
)
|
||||
|
||||
func ConfirmIssueSubmission(allowPreview bool, allowMetadata bool) (Action, error) {
|
||||
return confirmSubmission(allowPreview, allowMetadata, false, false)
|
||||
type Prompt interface {
|
||||
Input(string, string) (string, error)
|
||||
Select(string, string, []string) (int, error)
|
||||
MarkdownEditor(string, string, bool) (string, error)
|
||||
}
|
||||
|
||||
func ConfirmPRSubmission(allowPreview, allowMetadata, isDraft bool) (Action, error) {
|
||||
return confirmSubmission(allowPreview, allowMetadata, true, isDraft)
|
||||
func ConfirmIssueSubmission(p Prompt, allowPreview bool, allowMetadata bool) (Action, error) {
|
||||
return confirmSubmission(p, allowPreview, allowMetadata, false, false)
|
||||
}
|
||||
|
||||
func confirmSubmission(allowPreview, allowMetadata, allowDraft, isDraft bool) (Action, error) {
|
||||
func ConfirmPRSubmission(p Prompt, allowPreview, allowMetadata, isDraft bool) (Action, error) {
|
||||
return confirmSubmission(p, allowPreview, allowMetadata, true, isDraft)
|
||||
}
|
||||
|
||||
func confirmSubmission(p Prompt, allowPreview, allowMetadata, allowDraft, isDraft bool) (Action, error) {
|
||||
var options []string
|
||||
if !isDraft {
|
||||
options = append(options, submitLabel)
|
||||
|
|
@ -56,26 +61,12 @@ func confirmSubmission(allowPreview, allowMetadata, allowDraft, isDraft bool) (A
|
|||
}
|
||||
options = append(options, cancelLabel)
|
||||
|
||||
confirmAnswers := struct {
|
||||
Confirmation int
|
||||
}{}
|
||||
confirmQs := []*survey.Question{
|
||||
{
|
||||
Name: "confirmation",
|
||||
Prompt: &survey.Select{
|
||||
Message: "What's next?",
|
||||
Options: options,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
//nolint:staticcheck // SA1019: prompt.SurveyAsk is deprecated: use Prompter
|
||||
err := prompt.SurveyAsk(confirmQs, &confirmAnswers)
|
||||
result, err := p.Select("What's next?", "", options)
|
||||
if err != nil {
|
||||
return -1, fmt.Errorf("could not prompt: %w", err)
|
||||
}
|
||||
|
||||
switch options[confirmAnswers.Confirmation] {
|
||||
switch options[result] {
|
||||
case submitLabel:
|
||||
return SubmitAction, nil
|
||||
case submitDraftLabel:
|
||||
|
|
@ -87,11 +78,11 @@ func confirmSubmission(allowPreview, allowMetadata, allowDraft, isDraft bool) (A
|
|||
case cancelLabel:
|
||||
return CancelAction, nil
|
||||
default:
|
||||
return -1, fmt.Errorf("invalid index: %d", confirmAnswers.Confirmation)
|
||||
return -1, fmt.Errorf("invalid index: %d", result)
|
||||
}
|
||||
}
|
||||
|
||||
func BodySurvey(state *IssueMetadataState, templateContent, editorCommand string) error {
|
||||
func BodySurvey(p Prompt, state *IssueMetadataState, templateContent string) error {
|
||||
if templateContent != "" {
|
||||
if state.Body != "" {
|
||||
// prevent excessive newlines between default body and template
|
||||
|
|
@ -101,63 +92,32 @@ func BodySurvey(state *IssueMetadataState, templateContent, editorCommand string
|
|||
state.Body += templateContent
|
||||
}
|
||||
|
||||
preBody := state.Body
|
||||
|
||||
// TODO should just be an AskOne but ran into problems with the stubber
|
||||
qs := []*survey.Question{
|
||||
{
|
||||
Name: "Body",
|
||||
Prompt: &surveyext.GhEditor{
|
||||
BlankAllowed: true,
|
||||
EditorCommand: editorCommand,
|
||||
Editor: &survey.Editor{
|
||||
Message: "Body",
|
||||
FileName: "*.md",
|
||||
Default: state.Body,
|
||||
HideDefault: true,
|
||||
AppendDefault: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
//nolint:staticcheck // SA1019: prompt.SurveyAsk is deprecated: use Prompter
|
||||
err := prompt.SurveyAsk(qs, state)
|
||||
result, err := p.MarkdownEditor("Body", state.Body, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if preBody != state.Body {
|
||||
if state.Body != result {
|
||||
state.MarkDirty()
|
||||
}
|
||||
|
||||
state.Body = result
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func TitleSurvey(state *IssueMetadataState) error {
|
||||
preTitle := state.Title
|
||||
|
||||
// TODO should just be an AskOne but ran into problems with the stubber
|
||||
qs := []*survey.Question{
|
||||
{
|
||||
Name: "Title",
|
||||
Prompt: &survey.Input{
|
||||
Message: "Title",
|
||||
Default: state.Title,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
//nolint:staticcheck // SA1019: prompt.SurveyAsk is deprecated: use Prompter
|
||||
err := prompt.SurveyAsk(qs, state)
|
||||
func TitleSurvey(p Prompt, state *IssueMetadataState) error {
|
||||
result, err := p.Input("Title", state.Title)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if preTitle != state.Title {
|
||||
if result != state.Title {
|
||||
state.MarkDirty()
|
||||
}
|
||||
|
||||
state.Title = result
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue