mirror of
https://gitea.com/gitea/tea.git
synced 2026-10-26 11:01:25 +01:00
fix: address verified review findings (comments-views-search-1)
Signed-off-by: bircni <bircni@icloud.com>
This commit is contained in:
9 files changed
+68
-8
No files matched your search
@@ -246,12 +246,12 @@ func (a *application) writeComments(cmd *cobra.Command, t target, n int64, items
|
||||
text.WriteString(terminal.Table(nil, [][]terminal.Cell{{heading, {Text: meta, Muted: true}}}, d))
|
||||
body := strings.TrimSpace(comment.Body)
|
||||
if d.Markdown {
|
||||
body = strings.TrimSpace(terminal.Markdown(body, d))
|
||||
// Glamour already indents every line by its margin, which TrimSpace would strip from the first.
|
||||
text.WriteString(strings.Trim(terminal.Markdown(body, d), "\n"))
|
||||
} else {
|
||||
body = terminal.SafeText(body)
|
||||
}
|
||||
for line := range strings.Lines(body) {
|
||||
text.WriteString(" " + line)
|
||||
for line := range strings.Lines(terminal.SafeText(body)) {
|
||||
text.WriteString(" " + line)
|
||||
}
|
||||
}
|
||||
text.WriteString("\n")
|
||||
}
|
||||
@@ -283,6 +283,9 @@ $ tea %[1]s comment list %[2]s`, words.group, words.example), Annotations: map[s
|
||||
if deleteLast && (cmd.Flags().Changed("body") || cmd.Flags().Changed("body-file") || flags.useEditor) {
|
||||
return clierr.Wrap(clierr.Usage, errors.New("--delete-last takes no comment text"))
|
||||
}
|
||||
if deleteLast && a.options.json != "" {
|
||||
return clierr.Wrap(clierr.Usage, errors.New("comment deletion does not return a resource; --json and --jq are not supported"))
|
||||
}
|
||||
t, n, err := a.resolveRef(cmd, args[0], kind)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"gitea.dev/tea/internal/settings"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
@@ -151,6 +152,7 @@ func TestCommentGroupCommentsLikeGh(t *testing.T) {
|
||||
{[]string{"issue", "comment", "craete", "1"}, `unknown command "craete" for "tea issue comment"; did you mean create?`},
|
||||
{[]string{"issue", "comment", "-b", "x"}, "missing issue number"},
|
||||
{[]string{"issue", "comment", "1", "--edit-last", "--delete-last"}, "--edit-last and --delete-last cannot be combined"},
|
||||
{[]string{"issue", "comment", "1", "--delete-last", "--json"}, "comment deletion does not return a resource; --json and --jq are not supported"},
|
||||
{[]string{"issue", "comment", "1"}, "missing required input: supply --body, --body-file or --editor"},
|
||||
{[]string{"pr", "comment", "1", "-b", "x"}, "#1 in alice/project is an issue, not a pull request; use tea issue comment 1"},
|
||||
} {
|
||||
@@ -167,4 +169,26 @@ func TestCommentGroupCommentsLikeGh(t *testing.T) {
|
||||
require.Equal(t, "#79 alice • about 2 hours ago\n First **one**\n\n"+
|
||||
"#80 bob • about 1 hour ago (edited)\n Second\n line\n\n"+
|
||||
"#81 bob • about 50 minutes ago\n Third\n", out.String())
|
||||
// Rendered Markdown carries its own two-space margin, so every line of a body is indented alike.
|
||||
require.NoError(t, deps.Settings.Update(settings.TargetPreferences, func(s *settings.Snapshot) error {
|
||||
s.Preferences.Markdown, s.Preferences.Hyperlinks = "auto", "never"
|
||||
return nil
|
||||
}))
|
||||
require.NoError(t, run("issue", "comment", "list", "1"))
|
||||
require.Contains(t, out.String(), "\n Second\n line\n")
|
||||
require.NotContains(t, out.String(), " line")
|
||||
}
|
||||
|
||||
func TestViewCommentsCannotBeCombinedWithJSON(t *testing.T) {
|
||||
server := newAuthenticatedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
t.Errorf("unexpected %s %s", r.Method, r.URL.Path)
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
}))
|
||||
defer server.Close()
|
||||
deps, out, _ := serverDeps(t, server.URL)
|
||||
err := Execute(context.Background(), deps, []string{"issue", "view", "1", "-R", "alice/project", "--comments", "--json"})
|
||||
require.ErrorContains(t, err, "use tea issue comment list <number> --json")
|
||||
err = Execute(context.Background(), deps, []string{"pr", "view", "13", "-R", "alice/project", "--comments", "--json"})
|
||||
require.ErrorContains(t, err, "tea pr review list <number> --json")
|
||||
require.Empty(t, out.String())
|
||||
}
|
||||
@@ -88,13 +88,14 @@ func issueView(item services.Issue, repo string, dependencies services.IssueDepe
|
||||
}
|
||||
}
|
||||
|
||||
// dueText words a due date for people: "Dec 24, 2026 (in about 2 months)".
|
||||
// dueText words a due date for people: "Dec 24, 2026 (in about 2 months)". The day is the one in the
|
||||
// offset Gitea returned: it stores a due date as the end of a day in its own time zone.
|
||||
func dueText(now time.Time, raw string) string {
|
||||
due := terminal.ParseTime(raw)
|
||||
if due.IsZero() {
|
||||
return raw
|
||||
}
|
||||
return due.UTC().Format("Jan 2, 2006") + " (" + terminal.RelativeTime(now, due) + ")"
|
||||
return due.Format("Jan 2, 2006") + " (" + terminal.RelativeTime(now, due) + ")"
|
||||
}
|
||||
|
||||
// issueReferences lists issues as #N, qualifying those from other repositories.
|
||||
|
||||
@@ -189,3 +189,9 @@ func TestPullViewStates(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestDueTextKeepsTheDayInTheServerOffset(t *testing.T) {
|
||||
now := time.Date(2026, 10, 11, 20, 0, 0, 0, time.UTC)
|
||||
require.Equal(t, "Dec 24, 2026 (in about 2 months)", dueText(now, "2026-12-24T23:59:59-05:00"))
|
||||
require.Equal(t, "Dec 24, 2026 (in about 2 months)", dueText(now, "2026-12-24T23:59:59Z"))
|
||||
}
|
||||
@@ -168,6 +168,9 @@ func (a *application) issueViewCommand() *cobra.Command {
|
||||
conversation follows the body.`, Example: `$ tea issue view 12
|
||||
$ tea issue view 12 --comments
|
||||
$ tea issue view https://gitea.com/OWNER/REPO/issues/12 --web`, Annotations: map[string]string{"tea.arguments": issueArguments}, Args: argsExact(1), RunE: func(cmd *cobra.Command, args []string) error {
|
||||
if comments && a.options.json != "" {
|
||||
return clierr.Wrap(clierr.Usage, errors.New("--comments cannot be combined with --json or --jq; use tea issue comment list <number> --json"))
|
||||
}
|
||||
target, n, err := a.resolveRef(cmd, args[0], issueRef)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -143,6 +143,9 @@ func (a *application) jsonSelects(fields ...string) bool {
|
||||
func (a *application) pullViewCommand() *cobra.Command {
|
||||
var web, comments bool
|
||||
cmd := &cobra.Command{Use: "view [<number> | <url> | <branch>]", Short: "View a pull request", Annotations: pullArgumentsAnnotation(nil), Args: usageArgs(cobra.MaximumNArgs(1)), RunE: func(cmd *cobra.Command, args []string) error {
|
||||
if comments && a.options.json != "" {
|
||||
return clierr.Wrap(clierr.Usage, errors.New("--comments cannot be combined with --json or --jq; use tea pr comment list <number> --json or tea pr review list <number> --json"))
|
||||
}
|
||||
t, n, err := a.pullSelector(cmd, args)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -5,6 +5,8 @@ package services
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
gitea "gitea.dev/sdk"
|
||||
@@ -61,9 +63,18 @@ func (s Comments) Page(ctx context.Context, n int64, limit, page int) ([]Comment
|
||||
|
||||
// View retrieves a comment by its repository-scoped ID.
|
||||
func (s Comments) View(ctx context.Context, id int64) (Comment, error) {
|
||||
status := 0
|
||||
item, err := repoConvert(ctx, s.Client, s.Repository, commentFrom, func(ctx context.Context, c *gitea.Client, owner, repo string) (*gitea.Comment, *gitea.Response, error) {
|
||||
return c.Issues.GetIssueComment(ctx, owner, repo, id)
|
||||
comment, resp, err := c.Issues.GetIssueComment(ctx, owner, repo, id)
|
||||
if resp != nil && resp.Response != nil {
|
||||
status = resp.StatusCode
|
||||
}
|
||||
return comment, resp, err
|
||||
})
|
||||
if status == http.StatusNoContent {
|
||||
// Gitea answers without a body for the comments that are not plain ones, such as inline review comments.
|
||||
return Comment{}, fmt.Errorf("comment %d in %s is not a plain comment, such as an inline review comment, which this command cannot show", id, s.Repository)
|
||||
}
|
||||
return item, Classify(err, "comment", strconv.FormatInt(id, 10), s.Repository)
|
||||
}
|
||||
|
||||
|
||||
@@ -61,3 +61,11 @@ func TestRemoveMilestoneRejectsDifferentMembership(t *testing.T) {
|
||||
require.EqualError(t, err, `#7 is not in milestone "v1.0"`)
|
||||
require.Zero(t, mutations)
|
||||
}
|
||||
|
||||
func TestCommentViewExplainsAnEmptyAnswerForReviewComments(t *testing.T) {
|
||||
client := newTestClient(t, http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
}))
|
||||
_, err := Comments{Client: client, Repository: "alice/project"}.View(context.Background(), 9)
|
||||
require.EqualError(t, err, "comment 9 in alice/project is not a plain comment, such as an inline review comment, which this command cannot show")
|
||||
}
|
||||
Reference in new issue
Block a user