Merge createRun_issuesV2 cases into Test_createRun

Same code path, same scope. Test_createRun's httpStubs signature picks
up *testing.T to match the V2 cases that need it for input assertions.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Kynan Ware 2026-05-06 16:27:22 -06:00
parent 201eb7ec5e
commit a04438c22c

View file

@ -314,7 +314,7 @@ func Test_createRun(t *testing.T) {
tests := []struct {
name string
opts CreateOptions
httpStubs func(*httpmock.Registry)
httpStubs func(*testing.T, *httpmock.Registry)
promptStubs func(*prompter.PrompterMock)
wantsStdout string
wantsStderr string
@ -358,7 +358,7 @@ func Test_createRun(t *testing.T) {
WebMode: true,
Assignees: []string{"@me"},
},
httpStubs: func(r *httpmock.Registry) {
httpStubs: func(_ *testing.T, r *httpmock.Registry) {
r.Register(
httpmock.GraphQL(`query UserCurrent\b`),
httpmock.StringResponse(`
@ -386,7 +386,7 @@ func Test_createRun(t *testing.T) {
WebMode: true,
Projects: []string{"cleanup"},
},
httpStubs: func(r *httpmock.Registry) {
httpStubs: func(_ *testing.T, r *httpmock.Registry) {
r.Register(
httpmock.GraphQL(`query RepositoryProjectList\b`),
httpmock.StringResponse(`
@ -442,7 +442,7 @@ func Test_createRun(t *testing.T) {
Detector: &fd.EnabledDetectorMock{},
WebMode: true,
},
httpStubs: func(r *httpmock.Registry) {
httpStubs: func(_ *testing.T, r *httpmock.Registry) {
r.Register(
httpmock.GraphQL(`query IssueTemplates\b`),
httpmock.StringResponse(`
@ -468,7 +468,7 @@ func Test_createRun(t *testing.T) {
},
{
name: "editor",
httpStubs: func(r *httpmock.Registry) {
httpStubs: func(_ *testing.T, r *httpmock.Registry) {
r.Register(
httpmock.GraphQL(`query IssueRepositoryInfo\b`),
httpmock.StringResponse(`
@ -497,7 +497,7 @@ func Test_createRun(t *testing.T) {
},
{
name: "editor and template",
httpStubs: func(r *httpmock.Registry) {
httpStubs: func(_ *testing.T, r *httpmock.Registry) {
r.Register(
httpmock.GraphQL(`query IssueRepositoryInfo\b`),
httpmock.StringResponse(`
@ -579,7 +579,7 @@ func Test_createRun(t *testing.T) {
}
}
},
httpStubs: func(r *httpmock.Registry) {
httpStubs: func(_ *testing.T, r *httpmock.Registry) {
r.Register(
httpmock.GraphQL(`query IssueRepositoryInfo\b`),
httpmock.StringResponse(`
@ -652,7 +652,7 @@ func Test_createRun(t *testing.T) {
}
}
},
httpStubs: func(r *httpmock.Registry) {
httpStubs: func(_ *testing.T, r *httpmock.Registry) {
r.Register(
httpmock.GraphQL(`query IssueRepositoryInfo\b`),
httpmock.StringResponse(`
@ -686,13 +686,238 @@ func Test_createRun(t *testing.T) {
wantsStdout: "https://github.com/OWNER/REPO/issues/12\n",
wantsStderr: "\nCreating issue in OWNER/REPO\n\n",
},
{
name: "create with type",
opts: CreateOptions{
Detector: &fd.EnabledDetectorMock{},
Title: "bug title",
Body: "bug body",
IssueType: "Bug",
},
httpStubs: func(t *testing.T, r *httpmock.Registry) {
r.Register(
httpmock.GraphQL(`query IssueRepositoryInfo\b`),
httpmock.StringResponse(`
{ "data": { "repository": {
"id": "REPOID",
"hasIssuesEnabled": true
} } }`))
r.Register(
httpmock.GraphQL(`mutation IssueCreate\b`),
httpmock.StringResponse(`
{ "data": { "createIssue": { "issue": {
"id": "ISSUE_ID_123",
"URL": "https://github.com/OWNER/REPO/issues/123"
} } } }`))
r.Register(
httpmock.GraphQL(`query RepositoryIssueTypes\b`),
httpmock.StringResponse(`
{ "data": { "repository": { "issueTypes": { "nodes": [
{ "id": "IT_1", "name": "Bug", "description": "", "color": "d73a4a" },
{ "id": "IT_2", "name": "Feature", "description": "", "color": "0075ca" },
{ "id": "IT_3", "name": "Task", "description": "", "color": "e4e669" }
] } } } }`))
r.Register(
httpmock.GraphQL(`mutation UpdateIssueIssueType\b`),
httpmock.GraphQLMutation(`
{ "data": { "updateIssueIssueType": { "issue": { "id": "ISSUE_ID_123" } } } }`,
func(inputs map[string]interface{}) {
assert.Equal(t, "ISSUE_ID_123", inputs["issueId"])
assert.Equal(t, "IT_1", inputs["issueTypeId"])
}))
},
wantsStdout: "https://github.com/OWNER/REPO/issues/123\n",
wantsStderr: "\nCreating issue in OWNER/REPO\n\n",
},
{
name: "create with type not found",
opts: CreateOptions{
Detector: &fd.EnabledDetectorMock{},
Title: "bug title",
Body: "bug body",
IssueType: "Bugz",
},
httpStubs: func(_ *testing.T, r *httpmock.Registry) {
r.Register(
httpmock.GraphQL(`query IssueRepositoryInfo\b`),
httpmock.StringResponse(`
{ "data": { "repository": {
"id": "REPOID",
"hasIssuesEnabled": true
} } }`))
r.Register(
httpmock.GraphQL(`mutation IssueCreate\b`),
httpmock.StringResponse(`
{ "data": { "createIssue": { "issue": {
"id": "ISSUE_ID_123",
"URL": "https://github.com/OWNER/REPO/issues/123"
} } } }`))
r.Register(
httpmock.GraphQL(`query RepositoryIssueTypes\b`),
httpmock.StringResponse(`
{ "data": { "repository": { "issueTypes": { "nodes": [
{ "id": "IT_1", "name": "Bug", "description": "", "color": "d73a4a" },
{ "id": "IT_2", "name": "Feature", "description": "", "color": "0075ca" },
{ "id": "IT_3", "name": "Task", "description": "", "color": "e4e669" }
] } } } }`))
},
wantsErr: `type "Bugz" not found; available types: Bug, Feature, Task`,
},
{
name: "create with parent",
opts: CreateOptions{
Detector: &fd.EnabledDetectorMock{},
Title: "child issue",
Body: "child body",
Parent: "100",
},
httpStubs: func(t *testing.T, r *httpmock.Registry) {
r.Register(
httpmock.GraphQL(`query IssueRepositoryInfo\b`),
httpmock.StringResponse(`
{ "data": { "repository": {
"id": "REPOID",
"hasIssuesEnabled": true
} } }`))
r.Register(
httpmock.GraphQL(`mutation IssueCreate\b`),
httpmock.StringResponse(`
{ "data": { "createIssue": { "issue": {
"id": "ISSUE_ID_123",
"URL": "https://github.com/OWNER/REPO/issues/123"
} } } }`))
r.Register(
httpmock.GraphQL(`query IssueNodeID\b`),
httpmock.StringResponse(`
{ "data": { "repository": { "issue": { "id": "PARENT_ID_100" } } } }`))
r.Register(
httpmock.GraphQL(`mutation AddSubIssue\b`),
httpmock.GraphQLMutation(`
{ "data": { "addSubIssue": { "issue": { "id": "PARENT_ID_100" } } } }`,
func(inputs map[string]interface{}) {
assert.Equal(t, "PARENT_ID_100", inputs["issueId"])
assert.Equal(t, "ISSUE_ID_123", inputs["subIssueId"])
assert.Equal(t, false, inputs["replaceParent"])
}))
},
wantsStdout: "https://github.com/OWNER/REPO/issues/123\n",
wantsStderr: "\nCreating issue in OWNER/REPO\n\n",
},
{
name: "create with blocked-by and blocking",
opts: CreateOptions{
Detector: &fd.EnabledDetectorMock{},
Title: "blocked issue",
Body: "blocked body",
BlockedBy: []string{"200"},
Blocking: []string{"300"},
},
httpStubs: func(t *testing.T, r *httpmock.Registry) {
r.Register(
httpmock.GraphQL(`query IssueRepositoryInfo\b`),
httpmock.StringResponse(`
{ "data": { "repository": {
"id": "REPOID",
"hasIssuesEnabled": true
} } }`))
r.Register(
httpmock.GraphQL(`mutation IssueCreate\b`),
httpmock.StringResponse(`
{ "data": { "createIssue": { "issue": {
"id": "ISSUE_ID_123",
"URL": "https://github.com/OWNER/REPO/issues/123"
} } } }`))
// IssueNodeID for --blocked-by 200
r.Register(
httpmock.GraphQL(`query IssueNodeID\b`),
httpmock.StringResponse(`
{ "data": { "repository": { "issue": { "id": "BLOCKER_ID_200" } } } }`))
// AddBlockedBy for --blocked-by: new issue is blocked by #200
r.Register(
httpmock.GraphQL(`mutation AddBlockedBy\b`),
httpmock.GraphQLMutation(`
{ "data": { "addBlockedBy": { "issue": { "id": "ISSUE_ID_123" } } } }`,
func(inputs map[string]interface{}) {
assert.Equal(t, "ISSUE_ID_123", inputs["issueId"])
assert.Equal(t, "BLOCKER_ID_200", inputs["blockingIssueId"])
}))
// IssueNodeID for --blocking 300
r.Register(
httpmock.GraphQL(`query IssueNodeID\b`),
httpmock.StringResponse(`
{ "data": { "repository": { "issue": { "id": "BLOCKED_ID_300" } } } }`))
// AddBlockedBy for --blocking: #300 is blocked by new issue (swapped args)
r.Register(
httpmock.GraphQL(`mutation AddBlockedBy\b`),
httpmock.GraphQLMutation(`
{ "data": { "addBlockedBy": { "issue": { "id": "BLOCKED_ID_300" } } } }`,
func(inputs map[string]interface{}) {
assert.Equal(t, "BLOCKED_ID_300", inputs["issueId"])
assert.Equal(t, "ISSUE_ID_123", inputs["blockingIssueId"])
}))
},
wantsStdout: "https://github.com/OWNER/REPO/issues/123\n",
wantsStderr: "\nCreating issue in OWNER/REPO\n\n",
},
{
name: "blocked-by unsupported on GHES",
opts: CreateOptions{
Detector: &fd.DisabledDetectorMock{},
Title: "blocked issue",
Body: "blocked body",
BlockedBy: []string{"200"},
},
httpStubs: func(_ *testing.T, r *httpmock.Registry) {
r.Register(
httpmock.GraphQL(`query IssueRepositoryInfo\b`),
httpmock.StringResponse(`
{ "data": { "repository": {
"id": "REPOID",
"hasIssuesEnabled": true
} } }`))
r.Register(
httpmock.GraphQL(`mutation IssueCreate\b`),
httpmock.StringResponse(`
{ "data": { "createIssue": { "issue": {
"id": "ISSUE_ID_123",
"URL": "https://github.com/OWNER/REPO/issues/123"
} } } }`))
},
wantsErr: "issue relationships are not supported on this GitHub Enterprise Server version",
},
{
name: "blocking unsupported on GHES",
opts: CreateOptions{
Detector: &fd.DisabledDetectorMock{},
Title: "blocking issue",
Body: "blocking body",
Blocking: []string{"300"},
},
httpStubs: func(_ *testing.T, r *httpmock.Registry) {
r.Register(
httpmock.GraphQL(`query IssueRepositoryInfo\b`),
httpmock.StringResponse(`
{ "data": { "repository": {
"id": "REPOID",
"hasIssuesEnabled": true
} } }`))
r.Register(
httpmock.GraphQL(`mutation IssueCreate\b`),
httpmock.StringResponse(`
{ "data": { "createIssue": { "issue": {
"id": "ISSUE_ID_123",
"URL": "https://github.com/OWNER/REPO/issues/123"
} } } }`))
},
wantsErr: "issue relationships are not supported on this GitHub Enterprise Server version",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
httpReg := &httpmock.Registry{}
defer httpReg.Verify(t)
if tt.httpStubs != nil {
tt.httpStubs(httpReg)
tt.httpStubs(t, httpReg)
}
ios, _, stdout, stderr := iostreams.Test()
@ -1319,275 +1544,6 @@ func TestIssueCreate_projectsV2(t *testing.T) {
assert.Equal(t, "https://github.com/OWNER/REPO/issues/12\n", output.String())
}
func Test_createRun_issuesV2(t *testing.T) {
tests := []struct {
name string
opts CreateOptions
httpStubs func(*testing.T, *httpmock.Registry)
wantsStdout string
wantsStderr string
wantsErr string
}{
{
name: "create with type",
opts: CreateOptions{
Detector: &fd.EnabledDetectorMock{},
Title: "bug title",
Body: "bug body",
IssueType: "Bug",
},
httpStubs: func(t *testing.T, r *httpmock.Registry) {
r.Register(
httpmock.GraphQL(`query IssueRepositoryInfo\b`),
httpmock.StringResponse(`
{ "data": { "repository": {
"id": "REPOID",
"hasIssuesEnabled": true
} } }`))
r.Register(
httpmock.GraphQL(`mutation IssueCreate\b`),
httpmock.StringResponse(`
{ "data": { "createIssue": { "issue": {
"id": "ISSUE_ID_123",
"URL": "https://github.com/OWNER/REPO/issues/123"
} } } }`))
r.Register(
httpmock.GraphQL(`query RepositoryIssueTypes\b`),
httpmock.StringResponse(`
{ "data": { "repository": { "issueTypes": { "nodes": [
{ "id": "IT_1", "name": "Bug", "description": "", "color": "d73a4a" },
{ "id": "IT_2", "name": "Feature", "description": "", "color": "0075ca" },
{ "id": "IT_3", "name": "Task", "description": "", "color": "e4e669" }
] } } } }`))
r.Register(
httpmock.GraphQL(`mutation UpdateIssueIssueType\b`),
httpmock.GraphQLMutation(`
{ "data": { "updateIssueIssueType": { "issue": { "id": "ISSUE_ID_123" } } } }`,
func(inputs map[string]interface{}) {
assert.Equal(t, "ISSUE_ID_123", inputs["issueId"])
assert.Equal(t, "IT_1", inputs["issueTypeId"])
}))
},
wantsStdout: "https://github.com/OWNER/REPO/issues/123\n",
wantsStderr: "\nCreating issue in OWNER/REPO\n\n",
},
{
name: "create with type not found",
opts: CreateOptions{
Detector: &fd.EnabledDetectorMock{},
Title: "bug title",
Body: "bug body",
IssueType: "Bugz",
},
httpStubs: func(t *testing.T, r *httpmock.Registry) {
r.Register(
httpmock.GraphQL(`query IssueRepositoryInfo\b`),
httpmock.StringResponse(`
{ "data": { "repository": {
"id": "REPOID",
"hasIssuesEnabled": true
} } }`))
r.Register(
httpmock.GraphQL(`mutation IssueCreate\b`),
httpmock.StringResponse(`
{ "data": { "createIssue": { "issue": {
"id": "ISSUE_ID_123",
"URL": "https://github.com/OWNER/REPO/issues/123"
} } } }`))
r.Register(
httpmock.GraphQL(`query RepositoryIssueTypes\b`),
httpmock.StringResponse(`
{ "data": { "repository": { "issueTypes": { "nodes": [
{ "id": "IT_1", "name": "Bug", "description": "", "color": "d73a4a" },
{ "id": "IT_2", "name": "Feature", "description": "", "color": "0075ca" },
{ "id": "IT_3", "name": "Task", "description": "", "color": "e4e669" }
] } } } }`))
},
wantsErr: `type "Bugz" not found; available types: Bug, Feature, Task`,
},
{
name: "create with parent",
opts: CreateOptions{
Detector: &fd.EnabledDetectorMock{},
Title: "child issue",
Body: "child body",
Parent: "100",
},
httpStubs: func(t *testing.T, r *httpmock.Registry) {
r.Register(
httpmock.GraphQL(`query IssueRepositoryInfo\b`),
httpmock.StringResponse(`
{ "data": { "repository": {
"id": "REPOID",
"hasIssuesEnabled": true
} } }`))
r.Register(
httpmock.GraphQL(`mutation IssueCreate\b`),
httpmock.StringResponse(`
{ "data": { "createIssue": { "issue": {
"id": "ISSUE_ID_123",
"URL": "https://github.com/OWNER/REPO/issues/123"
} } } }`))
r.Register(
httpmock.GraphQL(`query IssueNodeID\b`),
httpmock.StringResponse(`
{ "data": { "repository": { "issue": { "id": "PARENT_ID_100" } } } }`))
r.Register(
httpmock.GraphQL(`mutation AddSubIssue\b`),
httpmock.GraphQLMutation(`
{ "data": { "addSubIssue": { "issue": { "id": "PARENT_ID_100" } } } }`,
func(inputs map[string]interface{}) {
assert.Equal(t, "PARENT_ID_100", inputs["issueId"])
assert.Equal(t, "ISSUE_ID_123", inputs["subIssueId"])
assert.Equal(t, false, inputs["replaceParent"])
}))
},
wantsStdout: "https://github.com/OWNER/REPO/issues/123\n",
wantsStderr: "\nCreating issue in OWNER/REPO\n\n",
},
{
name: "create with blocked-by and blocking",
opts: CreateOptions{
Detector: &fd.EnabledDetectorMock{},
Title: "blocked issue",
Body: "blocked body",
BlockedBy: []string{"200"},
Blocking: []string{"300"},
},
httpStubs: func(t *testing.T, r *httpmock.Registry) {
r.Register(
httpmock.GraphQL(`query IssueRepositoryInfo\b`),
httpmock.StringResponse(`
{ "data": { "repository": {
"id": "REPOID",
"hasIssuesEnabled": true
} } }`))
r.Register(
httpmock.GraphQL(`mutation IssueCreate\b`),
httpmock.StringResponse(`
{ "data": { "createIssue": { "issue": {
"id": "ISSUE_ID_123",
"URL": "https://github.com/OWNER/REPO/issues/123"
} } } }`))
// IssueNodeID for --blocked-by 200
r.Register(
httpmock.GraphQL(`query IssueNodeID\b`),
httpmock.StringResponse(`
{ "data": { "repository": { "issue": { "id": "BLOCKER_ID_200" } } } }`))
// AddBlockedBy for --blocked-by: new issue is blocked by #200
r.Register(
httpmock.GraphQL(`mutation AddBlockedBy\b`),
httpmock.GraphQLMutation(`
{ "data": { "addBlockedBy": { "issue": { "id": "ISSUE_ID_123" } } } }`,
func(inputs map[string]interface{}) {
assert.Equal(t, "ISSUE_ID_123", inputs["issueId"])
assert.Equal(t, "BLOCKER_ID_200", inputs["blockingIssueId"])
}))
// IssueNodeID for --blocking 300
r.Register(
httpmock.GraphQL(`query IssueNodeID\b`),
httpmock.StringResponse(`
{ "data": { "repository": { "issue": { "id": "BLOCKED_ID_300" } } } }`))
// AddBlockedBy for --blocking: #300 is blocked by new issue (swapped args)
r.Register(
httpmock.GraphQL(`mutation AddBlockedBy\b`),
httpmock.GraphQLMutation(`
{ "data": { "addBlockedBy": { "issue": { "id": "BLOCKED_ID_300" } } } }`,
func(inputs map[string]interface{}) {
assert.Equal(t, "BLOCKED_ID_300", inputs["issueId"])
assert.Equal(t, "ISSUE_ID_123", inputs["blockingIssueId"])
}))
},
wantsStdout: "https://github.com/OWNER/REPO/issues/123\n",
wantsStderr: "\nCreating issue in OWNER/REPO\n\n",
},
{
name: "blocked-by unsupported on GHES",
opts: CreateOptions{
Detector: &fd.DisabledDetectorMock{},
Title: "blocked issue",
Body: "blocked body",
BlockedBy: []string{"200"},
},
httpStubs: func(t *testing.T, r *httpmock.Registry) {
r.Register(
httpmock.GraphQL(`query IssueRepositoryInfo\b`),
httpmock.StringResponse(`
{ "data": { "repository": {
"id": "REPOID",
"hasIssuesEnabled": true
} } }`))
r.Register(
httpmock.GraphQL(`mutation IssueCreate\b`),
httpmock.StringResponse(`
{ "data": { "createIssue": { "issue": {
"id": "ISSUE_ID_123",
"URL": "https://github.com/OWNER/REPO/issues/123"
} } } }`))
},
wantsErr: "issue relationships are not supported on this GitHub Enterprise Server version",
},
{
name: "blocking unsupported on GHES",
opts: CreateOptions{
Detector: &fd.DisabledDetectorMock{},
Title: "blocking issue",
Body: "blocking body",
Blocking: []string{"300"},
},
httpStubs: func(t *testing.T, r *httpmock.Registry) {
r.Register(
httpmock.GraphQL(`query IssueRepositoryInfo\b`),
httpmock.StringResponse(`
{ "data": { "repository": {
"id": "REPOID",
"hasIssuesEnabled": true
} } }`))
r.Register(
httpmock.GraphQL(`mutation IssueCreate\b`),
httpmock.StringResponse(`
{ "data": { "createIssue": { "issue": {
"id": "ISSUE_ID_123",
"URL": "https://github.com/OWNER/REPO/issues/123"
} } } }`))
},
wantsErr: "issue relationships are not supported on this GitHub Enterprise Server version",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
httpReg := &httpmock.Registry{}
defer httpReg.Verify(t)
if tt.httpStubs != nil {
tt.httpStubs(t, httpReg)
}
ios, _, stdout, stderr := iostreams.Test()
ios.SetStdoutTTY(true)
opts := &tt.opts
opts.IO = ios
opts.HttpClient = func() (*http.Client, error) {
return &http.Client{Transport: httpReg}, nil
}
opts.BaseRepo = func() (ghrepo.Interface, error) {
return ghrepo.New("OWNER", "REPO"), nil
}
opts.Browser = &browser.Stub{}
err := createRun(opts)
if tt.wantsErr == "" {
require.NoError(t, err)
} else {
assert.EqualError(t, err, tt.wantsErr)
return
}
assert.Equal(t, tt.wantsStdout, stdout.String())
assert.Equal(t, tt.wantsStderr, stderr.String())
})
}
}
// TODO projectsV1Deprecation
// Remove this test.
func TestProjectsV1Deprecation(t *testing.T) {