diff --git a/pkg/cmd/issue/create/create.go b/pkg/cmd/issue/create/create.go index 8d47e4e27..4190fba3f 100644 --- a/pkg/cmd/issue/create/create.go +++ b/pkg/cmd/issue/create/create.go @@ -23,6 +23,8 @@ type CreateOptions struct { IO *iostreams.IOStreams BaseRepo func() (ghrepo.Interface, error) + RootDirOverride string + RepoOverride string WebMode bool @@ -94,9 +96,10 @@ func createRun(opts *CreateOptions) error { } var nonLegacyTemplateFiles []string - if opts.RepoOverride == "" { + if opts.RootDirOverride != "" { + nonLegacyTemplateFiles = githubtemplate.FindNonLegacy(opts.RootDirOverride, "ISSUE_TEMPLATE") + } else if opts.RepoOverride == "" { if rootDir, err := git.ToplevelDir(); err == nil { - // TODO: figure out how to stub this in tests nonLegacyTemplateFiles = githubtemplate.FindNonLegacy(rootDir, "ISSUE_TEMPLATE") } } diff --git a/pkg/cmd/issue/create/create_test.go b/pkg/cmd/issue/create/create_test.go index b483d090b..fb46e6e1e 100644 --- a/pkg/cmd/issue/create/create_test.go +++ b/pkg/cmd/issue/create/create_test.go @@ -16,6 +16,7 @@ import ( "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" @@ -29,6 +30,10 @@ func eq(t *testing.T, got interface{}, expected interface{}) { } func runCommand(rt http.RoundTripper, isTTY bool, cli string) (*test.CmdOut, error) { + return runCommandWithRootDirOverridden(rt, isTTY, cli, "") +} + +func runCommandWithRootDirOverridden(rt http.RoundTripper, isTTY bool, cli string, rootDir string) (*test.CmdOut, error) { io, _, stdout, stderr := iostreams.Test() io.SetStdoutTTY(isTTY) io.SetStdinTTY(isTTY) @@ -47,7 +52,10 @@ func runCommand(rt http.RoundTripper, isTTY bool, cli string) (*test.CmdOut, err }, } - cmd := NewCmdCreate(factory, nil) + cmd := NewCmdCreate(factory, func(opts *CreateOptions) error { + opts.RootDirOverride = rootDir + return createRun(opts) + }) argv, err := shlex.Split(cli) if err != nil { @@ -126,6 +134,67 @@ func TestIssueCreate(t *testing.T) { eq(t, output.String(), "https://github.com/OWNER/REPO/issues/12\n") } +func TestIssueCreate_nonLegacyTemplate(t *testing.T) { + http := &httpmock.Registry{} + defer http.Verify(t) + + http.StubResponse(200, bytes.NewBufferString(` + { "data": { "repository": { + "id": "REPOID", + "hasIssuesEnabled": true + } } } + `)) + http.StubResponse(200, bytes.NewBufferString(` + { "data": { "createIssue": { "issue": { + "URL": "https://github.com/OWNER/REPO/issues/12" + } } } } + `)) + + as, teardown := prompt.InitAskStubber() + defer teardown() + as.Stub([]*prompt.QuestionStub{ + { + Name: "index", + Value: 1, + }, + }) + as.Stub([]*prompt.QuestionStub{ + { + Name: "body", + Default: true, + }, + }) + as.Stub([]*prompt.QuestionStub{ + { + Name: "confirmation", + Value: 0, + }, + }) + + output, err := runCommandWithRootDirOverridden(http, true, `-t hello`, "./fixtures/repoWithNonLegacyIssueTemplates") + if err != nil { + t.Errorf("error running command `issue create`: %v", err) + } + + bodyBytes, _ := ioutil.ReadAll(http.Requests[1].Body) + reqBody := struct { + Variables struct { + Input struct { + RepositoryID string + Title string + Body string + } + } + }{} + _ = json.Unmarshal(bodyBytes, &reqBody) + + eq(t, reqBody.Variables.Input.RepositoryID, "REPOID") + eq(t, reqBody.Variables.Input.Title, "hello") + eq(t, reqBody.Variables.Input.Body, "I have a suggestion for an enhancement") + + eq(t, output.String(), "https://github.com/OWNER/REPO/issues/12\n") +} + func TestIssueCreate_metadata(t *testing.T) { http := &httpmock.Registry{} defer http.Verify(t) diff --git a/pkg/cmd/issue/create/fixtures/repoWithNonLegacyIssueTemplates/.github/ISSUE_TEMPLATE/bug_report.md b/pkg/cmd/issue/create/fixtures/repoWithNonLegacyIssueTemplates/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 000000000..d57082bcf --- /dev/null +++ b/pkg/cmd/issue/create/fixtures/repoWithNonLegacyIssueTemplates/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,9 @@ +--- +name: Bug report +about: Report a bug or unexpected behavior +title: Bug Report +labels: bug + +--- + +I wanna report a bug \ No newline at end of file diff --git a/pkg/cmd/issue/create/fixtures/repoWithNonLegacyIssueTemplates/.github/ISSUE_TEMPLATE/enhancement.md b/pkg/cmd/issue/create/fixtures/repoWithNonLegacyIssueTemplates/.github/ISSUE_TEMPLATE/enhancement.md new file mode 100644 index 000000000..0fe84afa3 --- /dev/null +++ b/pkg/cmd/issue/create/fixtures/repoWithNonLegacyIssueTemplates/.github/ISSUE_TEMPLATE/enhancement.md @@ -0,0 +1,9 @@ +--- +name: Submit a request +about: Propose an improvement +title: Enhancement Proposal +labels: enhancement + +--- + +I have a suggestion for an enhancement \ No newline at end of file diff --git a/pkg/cmd/pr/create/create.go b/pkg/cmd/pr/create/create.go index 6b144a5e9..233cdb38e 100644 --- a/pkg/cmd/pr/create/create.go +++ b/pkg/cmd/pr/create/create.go @@ -28,6 +28,8 @@ type CreateOptions struct { Remotes func() (context.Remotes, error) Branch func() (string, error) + RootDirOverride string + RepoOverride string Autofill bool @@ -246,8 +248,11 @@ func createRun(opts *CreateOptions) error { if !opts.WebMode && !opts.Autofill && interactive { var nonLegacyTemplateFiles []string var legacyTemplateFile *string - if rootDir, err := git.ToplevelDir(); err == nil { - // TODO: figure out how to stub this in tests + + if opts.RootDirOverride != "" { + nonLegacyTemplateFiles = githubtemplate.FindNonLegacy(opts.RootDirOverride, "PULL_REQUEST_TEMPLATE") + legacyTemplateFile = githubtemplate.FindLegacy(opts.RootDirOverride, "PULL_REQUEST_TEMPLATE") + } else if rootDir, err := git.ToplevelDir(); err == nil { nonLegacyTemplateFiles = githubtemplate.FindNonLegacy(rootDir, "PULL_REQUEST_TEMPLATE") legacyTemplateFile = githubtemplate.FindLegacy(rootDir, "PULL_REQUEST_TEMPLATE") } diff --git a/pkg/cmd/pr/create/create_test.go b/pkg/cmd/pr/create/create_test.go index e50a72c63..6b79551bf 100644 --- a/pkg/cmd/pr/create/create_test.go +++ b/pkg/cmd/pr/create/create_test.go @@ -31,6 +31,10 @@ func eq(t *testing.T, got interface{}, expected interface{}) { } func runCommand(rt http.RoundTripper, remotes context.Remotes, branch string, isTTY bool, cli string) (*test.CmdOut, error) { + return runCommandWithRootDirOverridden(rt, remotes, branch, isTTY, cli, "") +} + +func runCommandWithRootDirOverridden(rt http.RoundTripper, remotes context.Remotes, branch string, isTTY bool, cli string, rootDir string) (*test.CmdOut, error) { io, _, stdout, stderr := iostreams.Test() io.SetStdoutTTY(isTTY) io.SetStdinTTY(isTTY) @@ -60,7 +64,10 @@ func runCommand(rt http.RoundTripper, remotes context.Remotes, branch string, is }, } - cmd := NewCmdCreate(factory, nil) + cmd := NewCmdCreate(factory, func(opts *CreateOptions) error { + opts.RootDirOverride = rootDir + return createRun(opts) + }) cmd.PersistentFlags().StringP("repo", "R", "", "") argv, err := shlex.Split(cli) @@ -239,6 +246,80 @@ func TestPRCreate(t *testing.T) { eq(t, output.String(), "https://github.com/OWNER/REPO/pull/12\n") } +func TestPRCreate_nonLegacyTemplate(t *testing.T) { + http := initFakeHTTP() + defer http.Verify(t) + + http.StubRepoResponse("OWNER", "REPO") + http.StubResponse(200, bytes.NewBufferString(` + { "data": { "repository": { "forks": { "nodes": [ + ] } } } } + `)) + http.StubResponse(200, bytes.NewBufferString(` + { "data": { "repository": { "pullRequests": { "nodes" : [ + ] } } } } + `)) + http.StubResponse(200, bytes.NewBufferString(` + { "data": { "createPullRequest": { "pullRequest": { + "URL": "https://github.com/OWNER/REPO/pull/12" + } } } } + `)) + + cs, cmdTeardown := test.InitCmdStubber() + defer cmdTeardown() + + cs.Stub("") // git config --get-regexp (determineTrackingBranch) + cs.Stub("") // git show-ref --verify (determineTrackingBranch) + cs.Stub("") // git status + cs.Stub("1234567890,commit 0\n2345678901,commit 1") // git log + cs.Stub("") // git push + + as, teardown := prompt.InitAskStubber() + defer teardown() + as.Stub([]*prompt.QuestionStub{ + { + Name: "index", + Value: 0, + }, + }) + as.Stub([]*prompt.QuestionStub{ + { + Name: "body", + Default: true, + }, + }) + as.Stub([]*prompt.QuestionStub{ + { + Name: "confirmation", + Value: 0, + }, + }) + + output, err := runCommandWithRootDirOverridden(http, nil, "feature", true, `-t "my title"`, "./fixtures/repoWithNonLegacyPRTemplates") + require.NoError(t, err) + + bodyBytes, _ := ioutil.ReadAll(http.Requests[3].Body) + reqBody := struct { + Variables struct { + Input struct { + RepositoryID string + Title string + Body string + BaseRefName string + HeadRefName string + } + } + }{} + _ = json.Unmarshal(bodyBytes, &reqBody) + + eq(t, reqBody.Variables.Input.RepositoryID, "REPOID") + eq(t, reqBody.Variables.Input.Title, "my title") + eq(t, reqBody.Variables.Input.Body, "Fixes a bug and Closes an issue") + eq(t, reqBody.Variables.Input.BaseRefName, "master") + eq(t, reqBody.Variables.Input.HeadRefName, "feature") + + eq(t, output.String(), "https://github.com/OWNER/REPO/pull/12\n") +} func TestPRCreate_metadata(t *testing.T) { http := initFakeHTTP() diff --git a/pkg/cmd/pr/create/fixtures/repoWithNonLegacyPRTemplates/.github/PULL_REQUEST_TEMPLATE/bug_fix.md b/pkg/cmd/pr/create/fixtures/repoWithNonLegacyPRTemplates/.github/PULL_REQUEST_TEMPLATE/bug_fix.md new file mode 100644 index 000000000..5e98de344 --- /dev/null +++ b/pkg/cmd/pr/create/fixtures/repoWithNonLegacyPRTemplates/.github/PULL_REQUEST_TEMPLATE/bug_fix.md @@ -0,0 +1,7 @@ +--- +name: "Bug fix" +about: Fix a bug + +--- + +Fixes a bug and Closes an issue \ No newline at end of file