From e5fc3e9bbd281aeaaf4d07829f0fa81dfc0ac3c9 Mon Sep 17 00:00:00 2001 From: Corey Johnson Date: Tue, 28 Apr 2020 09:11:19 -0700 Subject: [PATCH 01/14] Update issue_test.go Add test for closing issue Co-Authored-By: Nate Smith --- command/issue_test.go | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/command/issue_test.go b/command/issue_test.go index b7f91031d..2185fc390 100644 --- a/command/issue_test.go +++ b/command/issue_test.go @@ -680,3 +680,25 @@ func TestIssueStateTitleWithColor(t *testing.T) { }) } } + +func TestIssueClose(t *testing.T) { + initBlankContext("", "OWNER/REPO", "master") + http := initFakeHTTP() + http.StubRepoResponse("OWNER", "REPO") + + jsonFile, _ := os.Open("../test/fixtures/issueClose.json") + defer jsonFile.Close() + http.StubResponse(200, jsonFile) + + output, err := RunCommand(issueStatusCmd, "issue close 13") + if err != nil { + t.Errorf("error running command `issue close`: %v", err) + } + + r := regexp.MustCompile(`WHATEVER!`) + + if !r.MatchString(output.String()) { + t.Errorf("output did not match regexp /%s/\n> output\n%s\n", r, output) + return + } +} From ad48d8b3c3dc9ff6053f20c662c18f0700ec5f1e Mon Sep 17 00:00:00 2001 From: Corey Johnson Date: Tue, 28 Apr 2020 09:13:08 -0700 Subject: [PATCH 02/14] Add issue close Co-Authored-By: Nate Smith --- api/queries_issue.go | 23 +++++++++++++++++++++++ command/issue.go | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/api/queries_issue.go b/api/queries_issue.go index cc01c039f..b9f569a08 100644 --- a/api/queries_issue.go +++ b/api/queries_issue.go @@ -1,10 +1,12 @@ package api import ( + "context" "fmt" "time" "github.com/cli/cli/internal/ghrepo" + "github.com/shurcooL/githubv4" ) type IssuesPayload struct { @@ -356,3 +358,24 @@ func IssueByNumber(client *Client, repo ghrepo.Interface, number int) (*Issue, e return &resp.Repository.Issue, nil } + +func IssueClose(client *Client, repo ghrepo.Interface, issueNumber int) error { + var mutation struct { + closeIssue struct { + } `graphql:"closeIssue(input: $input)"` + } + + input := githubv4.CloseIssueInput{ + IssueID: issueNumber, + } + + v4 := githubv4.NewClient(client.http) + err := v4.Mutate(context.Background(), &mutation, input, nil) + if err != nil { + return nil + } + + fmt.Printf("%v\n", mutation) + + return nil +} diff --git a/command/issue.go b/command/issue.go index 2f4e145af..0c2aae11b 100644 --- a/command/issue.go +++ b/command/issue.go @@ -39,6 +39,8 @@ func init() { issueCmd.AddCommand(issueViewCmd) issueViewCmd.Flags().BoolP("web", "w", false, "Open an issue in the browser") + + issueCmd.AddCommand(issueCloseCmd) } var issueCmd = &cobra.Command{ @@ -79,6 +81,12 @@ var issueViewCmd = &cobra.Command{ With '--web', open the issue in a web browser instead.`, RunE: issueView, } +var issueCloseCmd = &cobra.Command{ + Use: "close ", + Short: "close and issue issues", + Args: cobra.ExactArgs(1), + RunE: issueClose, +} func issueList(cmd *cobra.Command, args []string) error { ctx := contextForCommand(cmd) @@ -514,6 +522,31 @@ func issueProjectList(issue api.Issue) string { return list } +func issueClose(cmd *cobra.Command, args []string) error { + ctx := contextForCommand(cmd) + apiClient, err := apiClientForContext(ctx) + if err != nil { + return err + } + + baseRepo, err := determineBaseRepo(cmd, ctx) + if err != nil { + return err + } + + issueNumber, err := strconv.Atoi(args[0]) + if err != nil { + return fmt.Errorf("expected a number but: %w", err) + } + + err = api.IssueClose(apiClient, baseRepo, issueNumber) + if err != nil { + return fmt.Errorf("API call failed:%w", err) + } + + return nil +} + func displayURL(urlStr string) string { u, err := url.Parse(urlStr) if err != nil { From a2f0cc6de74a6b73ba1a1914a9ee7ea0ccaea261 Mon Sep 17 00:00:00 2001 From: Corey Johnson Date: Tue, 28 Apr 2020 09:31:19 -0700 Subject: [PATCH 03/14] Issue close works Co-Authored-By: Nate Smith --- api/queries_issue.go | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/api/queries_issue.go b/api/queries_issue.go index b9f569a08..7a342ccf3 100644 --- a/api/queries_issue.go +++ b/api/queries_issue.go @@ -22,6 +22,7 @@ type IssuesAndTotalCount struct { // Ref. https://developer.github.com/v4/object/issue/ type Issue struct { + ID string Number int Title string URL string @@ -298,6 +299,7 @@ func IssueByNumber(client *Client, repo ghrepo.Interface, number int) (*Issue, e repository(owner: $owner, name: $repo) { hasIssuesEnabled issue(number: $issue_number) { + id title state body @@ -360,22 +362,29 @@ func IssueByNumber(client *Client, repo ghrepo.Interface, number int) (*Issue, e } func IssueClose(client *Client, repo ghrepo.Interface, issueNumber int) error { + issue, err := IssueByNumber(client, repo, issueNumber) + if err != nil { + return fmt.Errorf("Faile to find issue #%d: %w", issueNumber, err) + } + var mutation struct { - closeIssue struct { + CloseIssue struct { + Issue struct { + ID githubv4.ID + } } `graphql:"closeIssue(input: $input)"` } input := githubv4.CloseIssueInput{ - IssueID: issueNumber, + IssueID: issue.ID, } v4 := githubv4.NewClient(client.http) - err := v4.Mutate(context.Background(), &mutation, input, nil) - if err != nil { - return nil - } + err = v4.Mutate(context.Background(), &mutation, input, nil) - fmt.Printf("%v\n", mutation) + if err != nil { + return err + } return nil } From 7ba66159194806fdacc169475b595b60cf7e9148 Mon Sep 17 00:00:00 2001 From: Corey Johnson Date: Tue, 28 Apr 2020 09:51:28 -0700 Subject: [PATCH 04/14] Close test now works Co-Authored-By: Nate Smith --- command/issue.go | 2 ++ command/issue_test.go | 15 +++++++++++---- test/fixtures/issueClose.json | 1 + 3 files changed, 14 insertions(+), 4 deletions(-) create mode 100644 test/fixtures/issueClose.json diff --git a/command/issue.go b/command/issue.go index 0c2aae11b..b919cc843 100644 --- a/command/issue.go +++ b/command/issue.go @@ -544,6 +544,8 @@ func issueClose(cmd *cobra.Command, args []string) error { return fmt.Errorf("API call failed:%w", err) } + fmt.Fprintf(colorableErr(cmd), "%s closed issue #%d\n", utils.Green("✔"), issueNumber) + return nil } diff --git a/command/issue_test.go b/command/issue_test.go index 2185fc390..5ba66f3ea 100644 --- a/command/issue_test.go +++ b/command/issue_test.go @@ -686,19 +686,26 @@ func TestIssueClose(t *testing.T) { http := initFakeHTTP() http.StubRepoResponse("OWNER", "REPO") + http.StubResponse(200, bytes.NewBufferString(` + { "data": { "repository": { + "hasIssuesEnabled": true, + "issue": { "id": "A-VERY-IMPORTANT-ID"} + } } } + `)) + jsonFile, _ := os.Open("../test/fixtures/issueClose.json") defer jsonFile.Close() http.StubResponse(200, jsonFile) - output, err := RunCommand(issueStatusCmd, "issue close 13") + output, err := RunCommand(issueCloseCmd, "issue close 13") if err != nil { t.Errorf("error running command `issue close`: %v", err) } - r := regexp.MustCompile(`WHATEVER!`) + r := regexp.MustCompile(`closed issue #13`) - if !r.MatchString(output.String()) { - t.Errorf("output did not match regexp /%s/\n> output\n%s\n", r, output) + if !r.MatchString(output.Stderr()) { + t.Errorf("output did not match regexp /%s/\n> output\n%q\n", r, output.Stderr()) return } } diff --git a/test/fixtures/issueClose.json b/test/fixtures/issueClose.json new file mode 100644 index 000000000..047f1a6a8 --- /dev/null +++ b/test/fixtures/issueClose.json @@ -0,0 +1 @@ +{ "id": "hi" } From bf94a3161990e202d0f5af6ab4ed56753b9d2226 Mon Sep 17 00:00:00 2001 From: Corey Johnson Date: Tue, 28 Apr 2020 10:05:56 -0700 Subject: [PATCH 05/14] not on issues disabled Co-Authored-By: Nate Smith --- api/queries_issue.go | 15 ++++++++++++--- command/issue_test.go | 23 +++++++++++++++++++++++ 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/api/queries_issue.go b/api/queries_issue.go index 7a342ccf3..9443ab8bf 100644 --- a/api/queries_issue.go +++ b/api/queries_issue.go @@ -2,6 +2,7 @@ package api import ( "context" + "errors" "fmt" "time" @@ -64,6 +65,10 @@ type Issue struct { } } +type IssuesDisabledError struct { + error +} + const fragments = ` fragment issue on Issue { number @@ -355,7 +360,8 @@ func IssueByNumber(client *Client, repo ghrepo.Interface, number int) (*Issue, e } if !resp.Repository.HasIssuesEnabled { - return nil, fmt.Errorf("the '%s' repository has disabled issues", ghrepo.FullName(repo)) + + return nil, &IssuesDisabledError{fmt.Errorf("the '%s' repository has disabled issues", ghrepo.FullName(repo))} } return &resp.Repository.Issue, nil @@ -363,8 +369,11 @@ func IssueByNumber(client *Client, repo ghrepo.Interface, number int) (*Issue, e func IssueClose(client *Client, repo ghrepo.Interface, issueNumber int) error { issue, err := IssueByNumber(client, repo, issueNumber) - if err != nil { - return fmt.Errorf("Faile to find issue #%d: %w", issueNumber, err) + var idErr *IssuesDisabledError + if errors.As(err, &idErr) { + return fmt.Errorf("issues disabled for %s", ghrepo.FullName(repo)) + } else if err != nil { + return fmt.Errorf("failed to find issue #%d: %w", issueNumber, err) } var mutation struct { diff --git a/command/issue_test.go b/command/issue_test.go index 5ba66f3ea..18976a4db 100644 --- a/command/issue_test.go +++ b/command/issue_test.go @@ -709,3 +709,26 @@ func TestIssueClose(t *testing.T) { return } } + +func TestIssueClose_issuesDisabled(t *testing.T) { + initBlankContext("", "OWNER/REPO", "master") + http := initFakeHTTP() + http.StubRepoResponse("OWNER", "REPO") + + http.StubResponse(200, bytes.NewBufferString(` + { "data": { "repository": { + "hasIssuesEnabled": false + } } } + `)) + + _, err := RunCommand(issueCloseCmd, "issue close 13") + if err == nil { + t.Fatalf("expected error when issues are disabled") + } + + if !strings.Contains(err.Error(), "issues disabled") { + t.Fatalf("got unexpected error: %s", err) + } + + return +} From f22f584e8d35fc6bb4b472ac64a7be3370bf2cf0 Mon Sep 17 00:00:00 2001 From: Corey Johnson Date: Tue, 28 Apr 2020 11:53:25 -0700 Subject: [PATCH 06/14] Handle closed issues --- api/queries_issue.go | 16 +++++++++++----- command/issue.go | 8 ++++++-- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/api/queries_issue.go b/api/queries_issue.go index 9443ab8bf..153336ea4 100644 --- a/api/queries_issue.go +++ b/api/queries_issue.go @@ -28,6 +28,7 @@ type Issue struct { Title string URL string State string + Closed bool Body string CreatedAt time.Time UpdatedAt time.Time @@ -307,6 +308,7 @@ func IssueByNumber(client *Client, repo ghrepo.Interface, number int) (*Issue, e id title state + closed body author { login @@ -367,13 +369,17 @@ func IssueByNumber(client *Client, repo ghrepo.Interface, number int) (*Issue, e return &resp.Repository.Issue, nil } -func IssueClose(client *Client, repo ghrepo.Interface, issueNumber int) error { +func IssueClose(client *Client, repo ghrepo.Interface, issueNumber int) (alreadyClosed bool, _ error) { issue, err := IssueByNumber(client, repo, issueNumber) var idErr *IssuesDisabledError if errors.As(err, &idErr) { - return fmt.Errorf("issues disabled for %s", ghrepo.FullName(repo)) + return false, fmt.Errorf("issues disabled for %s", ghrepo.FullName(repo)) } else if err != nil { - return fmt.Errorf("failed to find issue #%d: %w", issueNumber, err) + return false, fmt.Errorf("failed to find issue #%d: %w", issueNumber, err) + } + + if issue.Closed { + return true, nil } var mutation struct { @@ -392,8 +398,8 @@ func IssueClose(client *Client, repo ghrepo.Interface, issueNumber int) error { err = v4.Mutate(context.Background(), &mutation, input, nil) if err != nil { - return err + return false, err } - return nil + return false, nil } diff --git a/command/issue.go b/command/issue.go index b919cc843..d7562e875 100644 --- a/command/issue.go +++ b/command/issue.go @@ -539,12 +539,16 @@ func issueClose(cmd *cobra.Command, args []string) error { return fmt.Errorf("expected a number but: %w", err) } - err = api.IssueClose(apiClient, baseRepo, issueNumber) + alreadyClosed, err := api.IssueClose(apiClient, baseRepo, issueNumber) if err != nil { return fmt.Errorf("API call failed:%w", err) } - fmt.Fprintf(colorableErr(cmd), "%s closed issue #%d\n", utils.Green("✔"), issueNumber) + if alreadyClosed { + fmt.Fprintf(colorableErr(cmd), "%s issue #%d is already closed\n", utils.Yellow("!"), issueNumber) + } else { + fmt.Fprintf(colorableErr(cmd), "%s closed issue #%d\n", utils.Green("✔"), issueNumber) + } return nil } From 660cce7790fb468887982ced440ff4291733aa83 Mon Sep 17 00:00:00 2001 From: Corey Johnson Date: Tue, 28 Apr 2020 12:15:33 -0700 Subject: [PATCH 07/14] Take a URL --- api/queries_issue.go | 21 ++++----------------- command/issue.go | 23 ++++++++++++++--------- 2 files changed, 18 insertions(+), 26 deletions(-) diff --git a/api/queries_issue.go b/api/queries_issue.go index 153336ea4..ba9b43d65 100644 --- a/api/queries_issue.go +++ b/api/queries_issue.go @@ -2,7 +2,6 @@ package api import ( "context" - "errors" "fmt" "time" @@ -369,19 +368,7 @@ func IssueByNumber(client *Client, repo ghrepo.Interface, number int) (*Issue, e return &resp.Repository.Issue, nil } -func IssueClose(client *Client, repo ghrepo.Interface, issueNumber int) (alreadyClosed bool, _ error) { - issue, err := IssueByNumber(client, repo, issueNumber) - var idErr *IssuesDisabledError - if errors.As(err, &idErr) { - return false, fmt.Errorf("issues disabled for %s", ghrepo.FullName(repo)) - } else if err != nil { - return false, fmt.Errorf("failed to find issue #%d: %w", issueNumber, err) - } - - if issue.Closed { - return true, nil - } - +func IssueClose(client *Client, repo ghrepo.Interface, issue Issue) error { var mutation struct { CloseIssue struct { Issue struct { @@ -395,11 +382,11 @@ func IssueClose(client *Client, repo ghrepo.Interface, issueNumber int) (already } v4 := githubv4.NewClient(client.http) - err = v4.Mutate(context.Background(), &mutation, input, nil) + err := v4.Mutate(context.Background(), &mutation, input, nil) if err != nil { - return false, err + return err } - return false, nil + return nil } diff --git a/command/issue.go b/command/issue.go index d7562e875..02a378e30 100644 --- a/command/issue.go +++ b/command/issue.go @@ -534,23 +534,28 @@ func issueClose(cmd *cobra.Command, args []string) error { return err } - issueNumber, err := strconv.Atoi(args[0]) - if err != nil { - return fmt.Errorf("expected a number but: %w", err) + issue, err := issueFromArg(apiClient, baseRepo, args[0]) + var idErr *api.IssuesDisabledError + if errors.As(err, &idErr) { + return fmt.Errorf("issues disabled for %s", ghrepo.FullName(baseRepo)) + } else if err != nil { + return fmt.Errorf("failed to find issue #%d: %w", issue.Number, err) } - alreadyClosed, err := api.IssueClose(apiClient, baseRepo, issueNumber) + if issue.Closed { + fmt.Fprintf(colorableErr(cmd), "%s issue #%d is already closed\n", utils.Yellow("!"), issue.Number) + return nil + } + + err = api.IssueClose(apiClient, baseRepo, *issue) if err != nil { return fmt.Errorf("API call failed:%w", err) } - if alreadyClosed { - fmt.Fprintf(colorableErr(cmd), "%s issue #%d is already closed\n", utils.Yellow("!"), issueNumber) - } else { - fmt.Fprintf(colorableErr(cmd), "%s closed issue #%d\n", utils.Green("✔"), issueNumber) - } + fmt.Fprintf(colorableErr(cmd), "%s closed issue #%d\n", utils.Green("✔"), issue.Number) return nil + } func displayURL(urlStr string) string { From 99940fa0627d175b2c31d4438d8564d7e217efc1 Mon Sep 17 00:00:00 2001 From: Corey Johnson Date: Tue, 28 Apr 2020 12:15:37 -0700 Subject: [PATCH 08/14] Update test --- command/issue_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/command/issue_test.go b/command/issue_test.go index 18976a4db..ea3edbe2a 100644 --- a/command/issue_test.go +++ b/command/issue_test.go @@ -689,7 +689,7 @@ func TestIssueClose(t *testing.T) { http.StubResponse(200, bytes.NewBufferString(` { "data": { "repository": { "hasIssuesEnabled": true, - "issue": { "id": "A-VERY-IMPORTANT-ID"} + "issue": { "number": 13} } } } `)) From 69b58b95a3dee5f29f813f38282200d9e6a5b407 Mon Sep 17 00:00:00 2001 From: Corey Johnson Date: Tue, 28 Apr 2020 12:25:25 -0700 Subject: [PATCH 09/14] Fix linter errors --- command/issue_test.go | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/command/issue_test.go b/command/issue_test.go index ea3edbe2a..e723d665f 100644 --- a/command/issue_test.go +++ b/command/issue_test.go @@ -699,14 +699,13 @@ func TestIssueClose(t *testing.T) { output, err := RunCommand(issueCloseCmd, "issue close 13") if err != nil { - t.Errorf("error running command `issue close`: %v", err) + t.Fatalf("error running command `issue close`: %v", err) } r := regexp.MustCompile(`closed issue #13`) if !r.MatchString(output.Stderr()) { - t.Errorf("output did not match regexp /%s/\n> output\n%q\n", r, output.Stderr()) - return + t.Fatalf("output did not match regexp /%s/\n> output\n%q\n", r, output.Stderr()) } } @@ -729,6 +728,4 @@ func TestIssueClose_issuesDisabled(t *testing.T) { if !strings.Contains(err.Error(), "issues disabled") { t.Fatalf("got unexpected error: %s", err) } - - return } From 426c1e3460efd74459369f171aca2b4b6df51838 Mon Sep 17 00:00:00 2001 From: Corey Johnson Date: Tue, 28 Apr 2020 12:50:39 -0700 Subject: [PATCH 10/14] Make the checkmark red --- command/issue.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/command/issue.go b/command/issue.go index 02a378e30..45d52ab60 100644 --- a/command/issue.go +++ b/command/issue.go @@ -552,7 +552,7 @@ func issueClose(cmd *cobra.Command, args []string) error { return fmt.Errorf("API call failed:%w", err) } - fmt.Fprintf(colorableErr(cmd), "%s closed issue #%d\n", utils.Green("✔"), issue.Number) + fmt.Fprintf(colorableErr(cmd), "%s closed issue #%d\n", utils.Red("✔"), issue.Number) return nil From ab715638a4340423866291516081c84cfec48ca6 Mon Sep 17 00:00:00 2001 From: Corey Johnson Date: Tue, 28 Apr 2020 12:51:06 -0700 Subject: [PATCH 11/14] Case changes --- command/issue.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/command/issue.go b/command/issue.go index 45d52ab60..daa06e180 100644 --- a/command/issue.go +++ b/command/issue.go @@ -543,7 +543,7 @@ func issueClose(cmd *cobra.Command, args []string) error { } if issue.Closed { - fmt.Fprintf(colorableErr(cmd), "%s issue #%d is already closed\n", utils.Yellow("!"), issue.Number) + fmt.Fprintf(colorableErr(cmd), "%s Issue #%d is already closed\n", utils.Yellow("!"), issue.Number) return nil } @@ -552,7 +552,7 @@ func issueClose(cmd *cobra.Command, args []string) error { return fmt.Errorf("API call failed:%w", err) } - fmt.Fprintf(colorableErr(cmd), "%s closed issue #%d\n", utils.Red("✔"), issue.Number) + fmt.Fprintf(colorableErr(cmd), "%s Closed issue #%d\n", utils.Red("✔"), issue.Number) return nil From 1b37681a6f08ce759d6a778967c4dc8eaab64b81 Mon Sep 17 00:00:00 2001 From: Corey Johnson Date: Tue, 28 Apr 2020 12:57:24 -0700 Subject: [PATCH 12/14] Fix test --- command/issue_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/command/issue_test.go b/command/issue_test.go index e723d665f..1415386ba 100644 --- a/command/issue_test.go +++ b/command/issue_test.go @@ -702,7 +702,7 @@ func TestIssueClose(t *testing.T) { t.Fatalf("error running command `issue close`: %v", err) } - r := regexp.MustCompile(`closed issue #13`) + r := regexp.MustCompile(`Closed issue #13`) if !r.MatchString(output.Stderr()) { t.Fatalf("output did not match regexp /%s/\n> output\n%q\n", r, output.Stderr()) From 83ec49582b90dd074f89608d1212fdf773784961 Mon Sep 17 00:00:00 2001 From: Corey Johnson Date: Wed, 29 Apr 2020 11:31:40 -0700 Subject: [PATCH 13/14] get rid of fixture --- command/issue_test.go | 4 +--- test/fixtures/issueClose.json | 1 - 2 files changed, 1 insertion(+), 4 deletions(-) delete mode 100644 test/fixtures/issueClose.json diff --git a/command/issue_test.go b/command/issue_test.go index 1415386ba..cddab4efa 100644 --- a/command/issue_test.go +++ b/command/issue_test.go @@ -693,9 +693,7 @@ func TestIssueClose(t *testing.T) { } } } `)) - jsonFile, _ := os.Open("../test/fixtures/issueClose.json") - defer jsonFile.Close() - http.StubResponse(200, jsonFile) + http.StubResponse(200, bytes.NewBufferString(`{"id": "THE-ID"}`)) output, err := RunCommand(issueCloseCmd, "issue close 13") if err != nil { diff --git a/test/fixtures/issueClose.json b/test/fixtures/issueClose.json deleted file mode 100644 index 047f1a6a8..000000000 --- a/test/fixtures/issueClose.json +++ /dev/null @@ -1 +0,0 @@ -{ "id": "hi" } From c78c30b32fc73703e3ad9abed02c655f24cc646e Mon Sep 17 00:00:00 2001 From: Corey Johnson Date: Wed, 29 Apr 2020 11:33:16 -0700 Subject: [PATCH 14/14] Add already closed test --- command/issue_test.go | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/command/issue_test.go b/command/issue_test.go index cddab4efa..bddef2e30 100644 --- a/command/issue_test.go +++ b/command/issue_test.go @@ -707,6 +707,32 @@ func TestIssueClose(t *testing.T) { } } +func TestIssueClose_alreadyClosed(t *testing.T) { + initBlankContext("", "OWNER/REPO", "master") + http := initFakeHTTP() + http.StubRepoResponse("OWNER", "REPO") + + http.StubResponse(200, bytes.NewBufferString(` + { "data": { "repository": { + "hasIssuesEnabled": true, + "issue": { "number": 13, "closed": true} + } } } + `)) + + http.StubResponse(200, bytes.NewBufferString(`{"id": "THE-ID"}`)) + + output, err := RunCommand(issueCloseCmd, "issue close 13") + if err != nil { + t.Fatalf("error running command `issue close`: %v", err) + } + + r := regexp.MustCompile(`#13 is already closed`) + + if !r.MatchString(output.Stderr()) { + t.Fatalf("output did not match regexp /%s/\n> output\n%q\n", r, output.Stderr()) + } +} + func TestIssueClose_issuesDisabled(t *testing.T) { initBlankContext("", "OWNER/REPO", "master") http := initFakeHTTP()