Skip to content

Commit 882c081

Browse files
author
Nate Smith
authored
Merge pull request cli#3472 from cli/issue-create-web-fix
Fix `issue create --web`
2 parents 754dc10 + a2ff97d commit 882c081

File tree

2 files changed

+155
-118
lines changed

2 files changed

+155
-118
lines changed

pkg/cmd/issue/create/create.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,9 +157,8 @@ func createRun(opts *CreateOptions) (err error) {
157157

158158
tpl := shared.NewTemplateManager(httpClient, baseRepo, opts.RootDirOverride, !opts.HasRepoOverride, false)
159159

160-
var openURL string
161-
162160
if opts.WebMode {
161+
var openURL string
163162
if opts.Title != "" || opts.Body != "" || tb.HasMetadata() {
164163
openURL, err = generatePreviewURL(apiClient, baseRepo, tb)
165164
if err != nil {
@@ -171,6 +170,8 @@ func createRun(opts *CreateOptions) (err error) {
171170
}
172171
} else if ok, _ := tpl.HasTemplates(); ok {
173172
openURL = ghrepo.GenerateRepoURL(baseRepo, "issues/new/choose")
173+
} else {
174+
openURL = ghrepo.GenerateRepoURL(baseRepo, "issues/new")
174175
}
175176
if isTerminal {
176177
fmt.Fprintf(opts.IO.ErrOut, "Opening %s in your browser.\n", utils.DisplayURL(openURL))
@@ -193,6 +194,7 @@ func createRun(opts *CreateOptions) (err error) {
193194

194195
action := prShared.SubmitAction
195196
templateNameForSubmit := ""
197+
var openURL string
196198

197199
if opts.Interactive {
198200
var editorCommand string

pkg/cmd/issue/create/create_test.go

Lines changed: 151 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"net/http"
99
"os"
1010
"path/filepath"
11+
"strings"
1112
"testing"
1213

1314
"github.com/MakeNowJust/heredoc"
@@ -134,6 +135,156 @@ func TestNewCmdCreate(t *testing.T) {
134135
}
135136
}
136137

138+
func Test_createRun(t *testing.T) {
139+
tests := []struct {
140+
name string
141+
opts CreateOptions
142+
httpStubs func(*httpmock.Registry)
143+
wantsStdout string
144+
wantsStderr string
145+
wantsBrowse string
146+
wantsErr string
147+
}{
148+
{
149+
name: "no args",
150+
opts: CreateOptions{
151+
WebMode: true,
152+
},
153+
wantsBrowse: "https://github.com/OWNER/REPO/issues/new",
154+
wantsStderr: "Opening github.com/OWNER/REPO/issues/new in your browser.\n",
155+
},
156+
{
157+
name: "title and body",
158+
opts: CreateOptions{
159+
WebMode: true,
160+
Title: "myissue",
161+
Body: "hello cli",
162+
},
163+
wantsBrowse: "https://github.com/OWNER/REPO/issues/new?body=hello+cli&title=myissue",
164+
wantsStderr: "Opening github.com/OWNER/REPO/issues/new in your browser.\n",
165+
},
166+
{
167+
name: "assignee",
168+
opts: CreateOptions{
169+
WebMode: true,
170+
Assignees: []string{"monalisa"},
171+
},
172+
wantsBrowse: "https://github.com/OWNER/REPO/issues/new?assignees=monalisa",
173+
wantsStderr: "Opening github.com/OWNER/REPO/issues/new in your browser.\n",
174+
},
175+
{
176+
name: "@me",
177+
opts: CreateOptions{
178+
WebMode: true,
179+
Assignees: []string{"@me"},
180+
},
181+
httpStubs: func(r *httpmock.Registry) {
182+
r.Register(
183+
httpmock.GraphQL(`query UserCurrent\b`),
184+
httpmock.StringResponse(`
185+
{ "data": {
186+
"viewer": { "login": "MonaLisa" }
187+
} }`))
188+
},
189+
wantsBrowse: "https://github.com/OWNER/REPO/issues/new?assignees=MonaLisa",
190+
wantsStderr: "Opening github.com/OWNER/REPO/issues/new in your browser.\n",
191+
},
192+
{
193+
name: "project",
194+
opts: CreateOptions{
195+
WebMode: true,
196+
Projects: []string{"cleanup"},
197+
},
198+
httpStubs: func(r *httpmock.Registry) {
199+
r.Register(
200+
httpmock.GraphQL(`query RepositoryProjectList\b`),
201+
httpmock.StringResponse(`
202+
{ "data": { "repository": { "projects": {
203+
"nodes": [
204+
{ "name": "Cleanup", "id": "CLEANUPID", "resourcePath": "/OWNER/REPO/projects/1" }
205+
],
206+
"pageInfo": { "hasNextPage": false }
207+
} } } }`))
208+
r.Register(
209+
httpmock.GraphQL(`query OrganizationProjectList\b`),
210+
httpmock.StringResponse(`
211+
{ "data": { "organization": { "projects": {
212+
"nodes": [
213+
{ "name": "Triage", "id": "TRIAGEID", "resourcePath": "/orgs/ORG/projects/1" }
214+
],
215+
"pageInfo": { "hasNextPage": false }
216+
} } } }`))
217+
},
218+
wantsBrowse: "https://github.com/OWNER/REPO/issues/new?projects=OWNER%2FREPO%2F1",
219+
wantsStderr: "Opening github.com/OWNER/REPO/issues/new in your browser.\n",
220+
},
221+
{
222+
name: "has templates",
223+
opts: CreateOptions{
224+
WebMode: true,
225+
},
226+
httpStubs: func(r *httpmock.Registry) {
227+
r.Register(
228+
httpmock.GraphQL(`query IssueTemplates\b`),
229+
httpmock.StringResponse(`
230+
{ "data": { "repository": { "issueTemplates": [
231+
{ "name": "Bug report",
232+
"body": "Does not work :((" },
233+
{ "name": "Submit a request",
234+
"body": "I have a suggestion for an enhancement" }
235+
] } } }`),
236+
)
237+
},
238+
wantsBrowse: "https://github.com/OWNER/REPO/issues/new/choose",
239+
wantsStderr: "Opening github.com/OWNER/REPO/issues/new/choose in your browser.\n",
240+
},
241+
{
242+
name: "too long body",
243+
opts: CreateOptions{
244+
WebMode: true,
245+
Body: strings.Repeat("A", 9216),
246+
},
247+
wantsErr: "cannot open in browser: maximum URL length exceeded",
248+
},
249+
}
250+
for _, tt := range tests {
251+
t.Run(tt.name, func(t *testing.T) {
252+
httpReg := &httpmock.Registry{}
253+
defer httpReg.Verify(t)
254+
if tt.httpStubs != nil {
255+
tt.httpStubs(httpReg)
256+
}
257+
258+
io, _, stdout, stderr := iostreams.Test()
259+
io.SetStdoutTTY(true)
260+
opts := &tt.opts
261+
opts.IO = io
262+
opts.HttpClient = func() (*http.Client, error) {
263+
return &http.Client{Transport: httpReg}, nil
264+
}
265+
opts.BaseRepo = func() (ghrepo.Interface, error) {
266+
return ghrepo.New("OWNER", "REPO"), nil
267+
}
268+
browser := &cmdutil.TestBrowser{}
269+
opts.Browser = browser
270+
271+
err := createRun(opts)
272+
if tt.wantsErr == "" {
273+
require.NoError(t, err)
274+
} else {
275+
assert.EqualError(t, err, tt.wantsErr)
276+
return
277+
}
278+
279+
assert.Equal(t, tt.wantsStdout, stdout.String())
280+
assert.Equal(t, tt.wantsStderr, stderr.String())
281+
browser.Verify(t, tt.wantsBrowse)
282+
})
283+
}
284+
}
285+
286+
/*** LEGACY TESTS ***/
287+
137288
func runCommand(rt http.RoundTripper, isTTY bool, cli string) (*test.CmdOut, error) {
138289
return runCommandWithRootDirOverridden(rt, isTTY, cli, "")
139290
}
@@ -506,84 +657,6 @@ func TestIssueCreate_disabledIssues(t *testing.T) {
506657
}
507658
}
508659

509-
func TestIssueCreate_web(t *testing.T) {
510-
http := &httpmock.Registry{}
511-
defer http.Verify(t)
512-
513-
http.Register(
514-
httpmock.GraphQL(`query UserCurrent\b`),
515-
httpmock.StringResponse(`
516-
{ "data": {
517-
"viewer": { "login": "MonaLisa" }
518-
} }
519-
`),
520-
)
521-
522-
_, cmdTeardown := run.Stub()
523-
defer cmdTeardown(t)
524-
525-
output, err := runCommand(http, true, `--web -a @me`)
526-
if err != nil {
527-
t.Errorf("error running command `issue create`: %v", err)
528-
}
529-
530-
assert.Equal(t, "", output.String())
531-
assert.Equal(t, "Opening github.com/OWNER/REPO/issues/new in your browser.\n", output.Stderr())
532-
assert.Equal(t, "https://github.com/OWNER/REPO/issues/new?assignees=MonaLisa", output.BrowsedURL)
533-
}
534-
535-
func TestIssueCreate_webLongURL(t *testing.T) {
536-
longBodyFile := filepath.Join(t.TempDir(), "long-body.txt")
537-
err := ioutil.WriteFile(longBodyFile, make([]byte, 9216), 0600)
538-
require.NoError(t, err)
539-
540-
_, err = runCommand(nil, true, fmt.Sprintf("-F '%s' --web", longBodyFile))
541-
require.EqualError(t, err, "cannot open in browser: maximum URL length exceeded")
542-
}
543-
544-
func TestIssueCreate_webTitleBody(t *testing.T) {
545-
http := &httpmock.Registry{}
546-
defer http.Verify(t)
547-
548-
_, cmdTeardown := run.Stub()
549-
defer cmdTeardown(t)
550-
551-
output, err := runCommand(http, true, `-w -t mytitle -b mybody`)
552-
if err != nil {
553-
t.Errorf("error running command `issue create`: %v", err)
554-
}
555-
556-
assert.Equal(t, "", output.String())
557-
assert.Equal(t, "Opening github.com/OWNER/REPO/issues/new in your browser.\n", output.Stderr())
558-
assert.Equal(t, "https://github.com/OWNER/REPO/issues/new?body=mybody&title=mytitle", output.BrowsedURL)
559-
}
560-
561-
func TestIssueCreate_webTitleBodyAtMeAssignee(t *testing.T) {
562-
http := &httpmock.Registry{}
563-
defer http.Verify(t)
564-
565-
http.Register(
566-
httpmock.GraphQL(`query UserCurrent\b`),
567-
httpmock.StringResponse(`
568-
{ "data": {
569-
"viewer": { "login": "MonaLisa" }
570-
} }
571-
`),
572-
)
573-
574-
_, cmdTeardown := run.Stub()
575-
defer cmdTeardown(t)
576-
577-
output, err := runCommand(http, true, `-w -t mytitle -b mybody -a @me`)
578-
if err != nil {
579-
t.Errorf("error running command `issue create`: %v", err)
580-
}
581-
582-
assert.Equal(t, "", output.String())
583-
assert.Equal(t, "Opening github.com/OWNER/REPO/issues/new in your browser.\n", output.Stderr())
584-
assert.Equal(t, "https://github.com/OWNER/REPO/issues/new?assignees=MonaLisa&body=mybody&title=mytitle", output.BrowsedURL)
585-
}
586-
587660
func TestIssueCreate_AtMeAssignee(t *testing.T) {
588661
http := &httpmock.Registry{}
589662
defer http.Verify(t)
@@ -636,41 +709,3 @@ func TestIssueCreate_AtMeAssignee(t *testing.T) {
636709

637710
assert.Equal(t, "https://github.com/OWNER/REPO/issues/12\n", output.String())
638711
}
639-
640-
func TestIssueCreate_webProject(t *testing.T) {
641-
http := &httpmock.Registry{}
642-
defer http.Verify(t)
643-
644-
http.Register(
645-
httpmock.GraphQL(`query RepositoryProjectList\b`),
646-
httpmock.StringResponse(`
647-
{ "data": { "repository": { "projects": {
648-
"nodes": [
649-
{ "name": "Cleanup", "id": "CLEANUPID", "resourcePath": "/OWNER/REPO/projects/1" }
650-
],
651-
"pageInfo": { "hasNextPage": false }
652-
} } } }
653-
`))
654-
http.Register(
655-
httpmock.GraphQL(`query OrganizationProjectList\b`),
656-
httpmock.StringResponse(`
657-
{ "data": { "organization": { "projects": {
658-
"nodes": [
659-
{ "name": "Triage", "id": "TRIAGEID", "resourcePath": "/orgs/ORG/projects/1" }
660-
],
661-
"pageInfo": { "hasNextPage": false }
662-
} } } }
663-
`))
664-
665-
_, cmdTeardown := run.Stub()
666-
defer cmdTeardown(t)
667-
668-
output, err := runCommand(http, true, `-w -t Title -p Cleanup`)
669-
if err != nil {
670-
t.Errorf("error running command `issue create`: %v", err)
671-
}
672-
673-
assert.Equal(t, "", output.String())
674-
assert.Equal(t, "Opening github.com/OWNER/REPO/issues/new in your browser.\n", output.Stderr())
675-
assert.Equal(t, "https://github.com/OWNER/REPO/issues/new?projects=OWNER%2FREPO%2F1&title=Title", output.BrowsedURL)
676-
}

0 commit comments

Comments
 (0)