Files
gitea-tea/internal/app/issue_attachments_test.go
T
bircni ae0ea27bb0 fix: reconcile the issues stream and remove the legacy output shims
Use one canPrompt and pullNumberArguments for the comment commands, set
display preferences instead of the retired environment variables in
tests, and delete writeList, writeItem, batch, table, writeRecord(s),
the legacy column map, confirm, require, validateMilestoneFlags and
listWindow now that every command uses their replacements.

Signed-off-by: bircni <bircni@icloud.com>
2026-10-12 00:19:35 +02:00

136 lines
6.3 KiB
Go

// Copyright 2026 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package app
import (
"context"
"encoding/json"
"net/http"
"os"
"testing"
"time"
"gitea.dev/tea/internal/clierr"
"github.com/stretchr/testify/require"
)
func TestAttachmentCommandsShareIssueAssetsAndPagination(t *testing.T) {
server := newAuthenticatedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
require.Equal(t, http.MethodGet, r.Method)
switch r.URL.Path {
case "/api/v1/repos/alice/project/issues/1/assets":
_, _ = w.Write([]byte(`[{"id":1,"name":"one"},{"id":2,"name":"two"}]`))
case "/api/v1/repos/alice/project/issues/1/assets/1":
_, _ = w.Write([]byte(`{"id":1,"name":"one"}`))
case "/api/v1/repos/alice/project/issues/1":
_, _ = w.Write([]byte(`{"number":1,"pull_request":{}}`))
default:
t.Fatalf("unexpected path %s", r.URL.Path)
}
}))
defer server.Close()
for _, group := range []string{"issue", "pr"} {
deps, out, _ := serverDeps(t, server.URL)
require.NoError(t, Execute(context.Background(), deps, []string{group, "attachment", "list", "1", "--repo", "alice/project", "--limit=1", "--page=2", "--json=id,name"}))
require.JSONEq(t, `[{"id":2,"name":"two"}]`, out.String())
out.Reset()
require.NoError(t, Execute(context.Background(), deps, []string{group, "attachment", "list", "1", "--repo", "alice/project", "--limit=1", "--page=3", "--json"}))
require.JSONEq(t, `[]`, out.String())
out.Reset()
require.NoError(t, Execute(context.Background(), deps, []string{group, "attachment", "view", "1", "1", "--repo", "alice/project", "--json=id,name"}))
require.JSONEq(t, `{"id":1,"name":"one"}`, out.String())
}
}
func TestAttachmentRenameAndConfirmedDeletion(t *testing.T) {
for _, group := range []string{"issue", "pr"} {
mutations := 0
server := newAuthenticatedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Method == http.MethodGet && r.URL.Path == "/api/v1/repos/alice/project/issues/1" {
_, _ = w.Write([]byte(`{"number":1,"pull_request":{}}`))
return
}
if r.Method == http.MethodGet && r.URL.Path == "/api/v1/repos/alice/project/issues/1/assets/1" {
_, _ = w.Write([]byte(`{"id":1,"name":"log.txt"}`))
return
}
require.Equal(t, "/api/v1/repos/alice/project/issues/1/assets/1", r.URL.Path)
mutations++
if r.Method == http.MethodPatch {
var body map[string]string
require.NoError(t, json.NewDecoder(r.Body).Decode(&body))
require.Equal(t, "renamed.txt", body["name"])
_, _ = w.Write([]byte(`{"id":1,"name":"renamed.txt"}`))
} else {
require.Equal(t, http.MethodDelete, r.Method)
w.WriteHeader(http.StatusNoContent)
}
}))
deps, out, _ := serverDeps(t, server.URL)
require.NoError(t, Execute(context.Background(), deps, []string{group, "attachment", "edit", "1", "1", "--repo", "alice/project", "--name", "renamed.txt", "--json=name"}))
require.JSONEq(t, `{"name":"renamed.txt"}`, out.String())
out.Reset()
err := Execute(context.Background(), deps, []string{group, "attachment", "delete", "1", "1", "--repo", "alice/project", "--no-input"})
require.Error(t, err)
require.Equal(t, 1, mutations)
require.NoError(t, Execute(context.Background(), deps, []string{group, "attachment", "delete", "1", "1", "--repo", "alice/project", "--yes", "--no-input"}))
require.Equal(t, 2, mutations)
require.Empty(t, out.String())
for _, args := range [][]string{
{group, "attachment", "edit", "1", "1", "--name="},
{group, "attachment", "delete", "1", "1", "--json"},
} {
require.Equal(t, clierr.Usage, clierr.ExitCode(Execute(context.Background(), deps, args)))
}
require.Equal(t, 2, mutations)
server.Close()
}
}
func TestAttachmentTablesDownloadsAndDoneLines(t *testing.T) {
server := newAuthenticatedServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
switch r.Method + " " + r.URL.Path {
case "GET /api/v1/repos/alice/project/issues/1/assets":
_, _ = w.Write([]byte(`[{"id":9,"name":"crash.log","size":2048,"download_count":3,"created_at":"2026-10-11T18:00:00Z","browser_download_url":"https://example.org/a/9"}]`))
case "GET /api/v1/repos/alice/project/issues/1/assets/9":
_, _ = w.Write([]byte(`{"id":9,"name":"crash.log","size":5,"uuid":"abc"}`))
case "GET /attachments/abc":
_, _ = w.Write([]byte("hello"))
case "DELETE /api/v1/repos/alice/project/issues/1/assets/9":
w.WriteHeader(http.StatusNoContent)
default:
t.Errorf("unexpected %s %s", r.Method, r.URL.Path)
}
}))
defer server.Close()
deps, out, diagnostics := serverDeps(t, server.URL)
deps.Now = func() time.Time { return time.Date(2026, 10, 11, 20, 0, 0, 0, time.UTC) }
deps.Getenv = serverEnv(server.URL, map[string]string{"NO_COLOR": "1"})
plainOutput(t, deps)
run := func(tty bool, args ...string) error {
out.Reset()
diagnostics.Reset()
deps.Streams.OutTTY = tty
return Execute(context.Background(), deps, append(args, "-R", "alice/project", "--no-input"))
}
require.NoError(t, run(true, "issue", "attachment", "list", "1"))
require.Equal(t, "Showing 1 of 1 attachments on alice/project#1\n\n"+
"ID NAME SIZE DOWNLOADS CREATED\n"+
"9 crash.log 2.0 KiB 3 about 2 hours ago\n", out.String())
t.Chdir(t.TempDir())
require.NoError(t, run(true, "issue", "attachment", "download", "1", "9"))
require.Equal(t, "✓ Downloaded crash.log (5 B) to crash.log\n", diagnostics.String())
data, err := os.ReadFile("crash.log")
require.NoError(t, err)
require.Equal(t, "hello", string(data))
require.ErrorContains(t, run(true, "issue", "attachment", "download", "1", "9"), "crash.log already exists; pass --clobber to replace it or --skip-existing to keep it")
require.NoError(t, run(true, "issue", "attachment", "download", "1", "9", "--skip-existing"))
require.Equal(t, "! Skipped attachment 9 (crash.log) on alice/project#1: crash.log exists\n", diagnostics.String())
require.NoError(t, run(false, "issue", "attachment", "download", "1", "9", "-O", "-"))
require.Equal(t, "hello", out.String())
require.EqualError(t, run(true, "issue", "attachment", "delete", "1", "9"), "confirmation required to delete attachment 9 (crash.log) on alice/project#1; rerun with --yes")
require.NoError(t, run(true, "issue", "attachment", "delete", "1", "9", "--yes"))
require.Equal(t, "✓ Deleted attachment 9 (crash.log) on alice/project#1\n", diagnostics.String())
}