Add support for last comment edit by seachicken · Pull Request #6384 · cli/cli · GitHub
Skip to content
48 changes: 47 additions & 1 deletion api/queries_comments.go
4 changes: 4 additions & 0 deletions api/queries_issue.go
Original file line number Diff line number Diff line change
Expand Up @@ -244,3 +244,7 @@ func (i Issue) Link() string {
func (i Issue) Identifier() string {
return i.ID
}

func (i Issue) CurrentUserComments() []Comment {
return i.Comments.CurrentUserComments()
}
4 changes: 4 additions & 0 deletions api/queries_pr.go
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,10 @@ func (pr PullRequest) Identifier() string {
return pr.ID
}

func (pr PullRequest) CurrentUserComments() []Comment {
return pr.Comments.CurrentUserComments()
}

func (pr PullRequest) IsOpen() bool {
return pr.State == "OPEN"
}
Expand Down
5 changes: 5 additions & 0 deletions api/queries_pr_review.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ type PullRequestReviews struct {
}

type PullRequestReview struct {
ID string `json:"id"`
Author Author `json:"author"`
AuthorAssociation string `json:"authorAssociation"`
Body string `json:"body"`
Expand Down Expand Up @@ -67,6 +68,10 @@ func AddReview(client *Client, repo ghrepo.Interface, pr *PullRequest, input *Pu
return client.Mutate(repo.RepoHost(), "PullRequestReviewAdd", &mutation, variables)
}

func (prr PullRequestReview) Identifier() string {
return prr.ID
}

func (prr PullRequestReview) AuthorLogin() string {
return prr.Author.Login
}
Expand Down
5 changes: 4 additions & 1 deletion api/query_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,17 @@ func shortenQuery(q string) string {
var issueComments = shortenQuery(`
comments(first: 100) {
nodes {
id,
author{login},
authorAssociation,
body,
createdAt,
includesCreatedEdit,
isMinimized,
minimizedReason,
reactionGroups{content,users{totalCount}}
reactionGroups{content,users{totalCount}},
url,
viewerDidAuthor
},
pageInfo{hasNextPage,endCursor},
totalCount
Expand Down
7 changes: 6 additions & 1 deletion pkg/cmd/issue/comment/comment.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,11 @@ func NewCmdComment(f *cmdutil.Factory, runF func(*prShared.CommentableOptions) e
if err != nil {
return nil, nil, err
}
return issueShared.IssueFromArgWithFields(httpClient, f.BaseRepo, args[0], []string{"id", "url"})
fields := []string{"id", "url"}
if opts.EditLast {
fields = append(fields, "comments")
}
return issueShared.IssueFromArgWithFields(httpClient, f.BaseRepo, args[0], fields)
}
return prShared.CommentablePreRun(cmd, opts)
},
Expand All @@ -64,6 +68,7 @@ func NewCmdComment(f *cmdutil.Factory, runF func(*prShared.CommentableOptions) e
cmd.Flags().StringVarP(&bodyFile, "body-file", "F", "", "Read body text from `file` (use \"-\" to read from standard input)")
cmd.Flags().BoolP("editor", "e", false, "Skip prompts and open the text editor to write the body in")
cmd.Flags().BoolP("web", "w", false, "Open the web browser to write the comment")
cmd.Flags().BoolVar(&opts.EditLast, "edit-last", false, "Edit the last comment of the same author")

return cmd
}
93 changes: 81 additions & 12 deletions pkg/cmd/issue/comment/comment_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"path/filepath"
"testing"

"github.com/cli/cli/v2/api"
"github.com/cli/cli/v2/internal/browser"
"github.com/cli/cli/v2/internal/ghrepo"
"github.com/cli/cli/v2/pkg/cmd/pr/shared"
Expand Down Expand Up @@ -200,14 +201,30 @@ func Test_commentRun(t *testing.T) {
InputType: 0,
Body: "",

InteractiveEditSurvey: func() (string, error) { return "comment body", nil },
InteractiveEditSurvey: func(string) (string, error) { return "comment body", nil },
ConfirmSubmitSurvey: func() (bool, error) { return true, nil },
},
httpStubs: func(t *testing.T, reg *httpmock.Registry) {
mockCommentCreate(t, reg)
},
stdout: "https://github.com/OWNER/REPO/issues/123#issuecomment-456\n",
},
{
name: "interactive editor with edit last",
input: &shared.CommentableOptions{
Interactive: true,
InputType: 0,
Body: "",
EditLast: true,

InteractiveEditSurvey: func(string) (string, error) { return "comment body", nil },
ConfirmSubmitSurvey: func() (bool, error) { return true, nil },
},
httpStubs: func(t *testing.T, reg *httpmock.Registry) {
mockCommentUpdate(t, reg)
},
stdout: "https://github.com/OWNER/REPO/issues/123#issuecomment-111\n",
},
{
name: "non-interactive web",
input: &shared.CommentableOptions{
Expand All @@ -219,20 +236,47 @@ func Test_commentRun(t *testing.T) {
},
stderr: "Opening github.com/OWNER/REPO/issues/123 in your browser.\n",
},
{
name: "non-interactive web with edit last",
input: &shared.CommentableOptions{
Interactive: false,
InputType: shared.InputTypeWeb,
Body: "",
EditLast: true,

OpenInBrowser: func(string) error { return nil },
},
stderr: "Opening github.com/OWNER/REPO/issues/123 in your browser.\n",
},
{
name: "non-interactive editor",
input: &shared.CommentableOptions{
Interactive: false,
InputType: shared.InputTypeEditor,
Body: "",

EditSurvey: func() (string, error) { return "comment body", nil },
EditSurvey: func(string) (string, error) { return "comment body", nil },
},
httpStubs: func(t *testing.T, reg *httpmock.Registry) {
mockCommentCreate(t, reg)
},
stdout: "https://github.com/OWNER/REPO/issues/123#issuecomment-456\n",
},
{
name: "non-interactive editor with edit last",
input: &shared.CommentableOptions{
Interactive: false,
InputType: shared.InputTypeEditor,
Body: "",
EditLast: true,

EditSurvey: func(string) (string, error) { return "comment body", nil },
},
httpStubs: func(t *testing.T, reg *httpmock.Registry) {
mockCommentUpdate(t, reg)
},
stdout: "https://github.com/OWNER/REPO/issues/123#issuecomment-111\n",
},
{
name: "non-interactive inline",
input: &shared.CommentableOptions{
Expand All @@ -245,6 +289,19 @@ func Test_commentRun(t *testing.T) {
},
stdout: "https://github.com/OWNER/REPO/issues/123#issuecomment-456\n",
},
{
name: "non-interactive inline with edit last",
input: &shared.CommentableOptions{
Interactive: false,
InputType: shared.InputTypeInline,
Body: "comment body",
EditLast: true,
},
httpStubs: func(t *testing.T, reg *httpmock.Registry) {
mockCommentUpdate(t, reg)
},
stdout: "https://github.com/OWNER/REPO/issues/123#issuecomment-111\n",
},
}
for _, tt := range tests {
ios, _, stdout, stderr := iostreams.Test()
Expand All @@ -263,7 +320,14 @@ func Test_commentRun(t *testing.T) {
return &http.Client{Transport: reg}, nil
}
tt.input.RetrieveCommentable = func() (shared.Commentable, ghrepo.Interface, error) {
return &mockCommentable{}, ghrepo.New("OWNER", "REPO"), nil
return &api.Issue{
ID: "ISSUE-ID",
URL: "https://github.com/OWNER/REPO/issues/123",
Comments: api.Comments{Nodes: []api.Comment{
{ID: "id1", Author: api.Author{Login: "octocat"}, URL: "https://github.com/OWNER/REPO/issues/123#issuecomment-111", ViewerDidAuthor: true},
{ID: "id2", Author: api.Author{Login: "monalisa"}, URL: "https://github.com/OWNER/REPO/issues/123#issuecomment-222"},
}},
}, ghrepo.New("OWNER", "REPO"), nil
}

t.Run(tt.name, func(t *testing.T) {
Expand All @@ -275,15 +339,6 @@ func Test_commentRun(t *testing.T) {
}
}

type mockCommentable struct{}

func (c mockCommentable) Identifier() string {
return "ISSUE-ID"
}
func (c mockCommentable) Link() string {
return "https://github.com/OWNER/REPO/issues/123"
}

func mockCommentCreate(t *testing.T, reg *httpmock.Registry) {
reg.Register(
httpmock.GraphQL(`mutation CommentCreate\b`),
Expand All @@ -297,3 +352,17 @@ func mockCommentCreate(t *testing.T, reg *httpmock.Registry) {
}),
)
}

func mockCommentUpdate(t *testing.T, reg *httpmock.Registry) {
reg.Register(
httpmock.GraphQL(`mutation CommentUpdate\b`),
httpmock.GraphQLMutation(`
{ "data": { "updateIssueComment": { "issueComment": {
"url": "https://github.com/OWNER/REPO/issues/123#issuecomment-111"
} } } }`,
func(inputs map[string]interface{}) {
assert.Equal(t, "id1", inputs["id"])
assert.Equal(t, "comment body", inputs["body"])
}),
)
}
7 changes: 6 additions & 1 deletion pkg/cmd/pr/comment/comment.go
Loading