package view
import (
"io"
"net/http"
"strings"
"testing"
cmdutil "gitcode.com/gitcode-cli/cli/pkg/cmdutil"
"gitcode.com/gitcode-cli/cli/pkg/iostreams"
"gitcode.com/gitcode-cli/cli/pkg/testutil"
)
func httpFactory(client *http.Client) func() (*http.Client, error) {
return func() (*http.Client, error) { return client, nil }
}
func TestNewCmdView(t *testing.T) {
tests := []struct {
name string
args []string
wantErr bool
}{
{name: "valid", args: []string{"42", "-R", "owner/repo"}, wantErr: false},
{name: "non-numeric", args: []string{"abc", "-R", "owner/repo"}, wantErr: true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
f := cmdutil.TestFactory()
cmd := NewCmdView(f, func(opts *ViewOptions) error { return nil })
cmd.SetArgs(tt.args)
err := cmd.Execute()
if (err != nil) != tt.wantErr {
t.Errorf("Execute() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
func TestViewRunText(t *testing.T) {
t.Setenv("GC_TOKEN", "test-token")
body := `{"id":"a","number":42,"title":"release plan","md_content":"body text","comment_total":3,"is_closed":0,"author":{"login":"alice"},"created_at":"2026-07-13T10:00:00Z","updated_at":"2026-07-14T11:00:00Z"}`
var gotPath string
client := &http.Client{
Transport: testutil.NewRoundTripFunc(func(req *http.Request) (*http.Response, error) {
gotPath = req.URL.Path
return &http.Response{
StatusCode: http.StatusOK, Status: http.StatusText(http.StatusOK),
Header: make(http.Header),
Body: io.NopCloser(strings.NewReader(body)),
}, nil
}),
}
ios, _, out, _ := iostreams.Test()
err := viewRun(&ViewOptions{IO: ios, HttpClient: httpFactory(client), Repository: "owner/repo", Number: 42})
if err != nil {
t.Fatalf("viewRun() error = %v", err)
}
if gotPath != "/api/v5/repos/owner/repo/discuss/42" {
t.Fatalf("path = %q, want /api/v5/repos/owner/repo/discuss/42", gotPath)
}
if !strings.Contains(out.String(), "release plan") || !strings.Contains(out.String(), "body text") {
t.Fatalf("output = %q, want title + md_content", out.String())
}
}
func TestViewRunJSON(t *testing.T) {
t.Setenv("GC_TOKEN", "test-token")
body := `{"id":"a","number":42,"title":"release plan","comment_total":3}`
client := &http.Client{
Transport: testutil.NewRoundTripFunc(func(req *http.Request) (*http.Response, error) {
return &http.Response{
StatusCode: http.StatusOK, Status: http.StatusText(http.StatusOK),
Header: make(http.Header),
Body: io.NopCloser(strings.NewReader(body)),
}, nil
}),
}
ios, _, out, _ := iostreams.Test()
err := viewRun(&ViewOptions{IO: ios, HttpClient: httpFactory(client), Repository: "owner/repo", Number: 42, JSON: true})
if err != nil {
t.Fatalf("viewRun() error = %v", err)
}
if !strings.Contains(out.String(), `"release plan"`) || !strings.Contains(out.String(), `"number": 42`) {
t.Fatalf("output = %q, want JSON", out.String())
}
}
func TestViewRunNotFoundExit3(t *testing.T) {
t.Setenv("GC_TOKEN", "test-token")
client := &http.Client{
Transport: testutil.NewRoundTripFunc(func(req *http.Request) (*http.Response, error) {
return &http.Response{
StatusCode: http.StatusNotFound, Status: http.StatusText(http.StatusNotFound),
Header: make(http.Header),
Body: io.NopCloser(strings.NewReader(`{"message":"not found"}`)),
}, nil
}),
}
ios, _, _, _ := iostreams.Test()
err := viewRun(&ViewOptions{IO: ios, HttpClient: httpFactory(client), Repository: "owner/repo", Number: 999})
if err == nil {
t.Fatal("viewRun() error = nil, want not-found")
}
if got := cmdutil.ExitCode(err); got != cmdutil.ExitNotFound {
t.Fatalf("ExitCode = %d, want ExitNotFound(%d)", got, cmdutil.ExitNotFound)
}
}
func TestViewRunNumberMustBePositive(t *testing.T) {
t.Setenv("GC_TOKEN", "test-token")
ios, _, _, _ := iostreams.Test()
err := viewRun(&ViewOptions{IO: ios, HttpClient: httpFactory(&http.Client{}), Repository: "owner/repo", Number: 0})
if err == nil {
t.Fatal("viewRun() error = nil, want usage error for number < 1")
}
if got := cmdutil.ExitCode(err); got != cmdutil.ExitUsage {
t.Fatalf("ExitCode = %d, want ExitUsage(%d)", got, cmdutil.ExitUsage)
}
}