diff --git a/pkg/cmd/gist/view/view.go b/pkg/cmd/gist/view/view.go index cbe735675..fecb69adb 100644 --- a/pkg/cmd/gist/view/view.go +++ b/pkg/cmd/gist/view/view.go @@ -4,6 +4,7 @@ import ( "fmt" "net/http" "net/url" + "sort" "strings" "github.com/cli/cli/internal/ghinstance" @@ -105,10 +106,12 @@ func viewRun(opts *ViewOptions) error { showFilenames := len(gist.Files) > 1 + outs := []string{} // to ensure consistent ordering + for filename, gistFile := range gist.Files { + out := "" if showFilenames { - fmt.Fprintf(opts.IO.Out, "%s\n", cs.Gray(filename)) - fmt.Fprintln(opts.IO.Out) + out += fmt.Sprintf("%s\n\n", cs.Gray(filename)) } content := gistFile.Content if strings.Contains(gistFile.Type, "markdown") && !opts.Raw { @@ -117,8 +120,15 @@ func viewRun(opts *ViewOptions) error { content = rendered } } - fmt.Fprintf(opts.IO.Out, "%s\n", content) - fmt.Fprintln(opts.IO.Out) + out += fmt.Sprintf("%s\n\n", content) + + outs = append(outs, out) + } + + sort.Strings(outs) + + for _, out := range outs { + fmt.Fprint(opts.IO.Out, out) } return nil diff --git a/pkg/cmd/gist/view/view_test.go b/pkg/cmd/gist/view/view_test.go index d77ab946d..0ddc33181 100644 --- a/pkg/cmd/gist/view/view_test.go +++ b/pkg/cmd/gist/view/view_test.go @@ -2,9 +2,12 @@ package view import ( "bytes" + "net/http" "testing" + "github.com/cli/cli/pkg/cmd/gist/shared" "github.com/cli/cli/pkg/cmdutil" + "github.com/cli/cli/pkg/httpmock" "github.com/cli/cli/pkg/iostreams" "github.com/google/shlex" "github.com/stretchr/testify/assert" @@ -34,6 +37,16 @@ func TestNewCmdView(t *testing.T) { Selector: "123", }, }, + { + name: "filename passed", + cli: "-fcool.txt 123", + tty: true, + wants: ViewOptions{ + Raw: false, + Selector: "123", + Filename: "cool.txt", + }, + }, } for _, tt := range tests { @@ -63,8 +76,142 @@ func TestNewCmdView(t *testing.T) { assert.Equal(t, tt.wants.Raw, gotOpts.Raw) assert.Equal(t, tt.wants.Selector, gotOpts.Selector) + assert.Equal(t, tt.wants.Filename, gotOpts.Filename) }) } } -// TODO execution tests +func Test_viewRun(t *testing.T) { + tests := []struct { + name string + opts *ViewOptions + wantOut string + gist *shared.Gist + wantErr bool + }{ + { + name: "no such gist", + wantErr: true, + }, + { + name: "one file", + gist: &shared.Gist{ + Files: map[string]*shared.GistFile{ + "cicada.txt": { + Content: "bwhiizzzbwhuiiizzzz", + Type: "text/plain", + }, + }, + }, + wantOut: "bwhiizzzbwhuiiizzzz\n\n", + }, + { + name: "filename selected", + opts: &ViewOptions{ + Filename: "cicada.txt", + }, + gist: &shared.Gist{ + Files: map[string]*shared.GistFile{ + "cicada.txt": { + Content: "bwhiizzzbwhuiiizzzz", + Type: "text/plain", + }, + "foo.md": { + Content: "# foo", + Type: "application/markdown", + }, + }, + }, + wantOut: "bwhiizzzbwhuiiizzzz\n\n", + }, + { + name: "multiple files, no description", + gist: &shared.Gist{ + Files: map[string]*shared.GistFile{ + "cicada.txt": { + Content: "bwhiizzzbwhuiiizzzz", + Type: "text/plain", + }, + "foo.md": { + Content: "# foo", + Type: "application/markdown", + }, + }, + }, + wantOut: "cicada.txt\n\nbwhiizzzbwhuiiizzzz\n\nfoo.md\n\n\n # foo \n\n\n\n", + }, + { + name: "multiple files, description", + gist: &shared.Gist{ + Description: "some files", + Files: map[string]*shared.GistFile{ + "cicada.txt": { + Content: "bwhiizzzbwhuiiizzzz", + Type: "text/plain", + }, + "foo.md": { + Content: "- foo", + Type: "application/markdown", + }, + }, + }, + wantOut: "some files\ncicada.txt\n\nbwhiizzzbwhuiiizzzz\n\nfoo.md\n\n\n \n • foo \n\n\n\n", + }, + { + name: "raw", + opts: &ViewOptions{ + Raw: true, + }, + gist: &shared.Gist{ + Description: "some files", + Files: map[string]*shared.GistFile{ + "cicada.txt": { + Content: "bwhiizzzbwhuiiizzzz", + Type: "text/plain", + }, + "foo.md": { + Content: "- foo", + Type: "application/markdown", + }, + }, + }, + wantOut: "some files\ncicada.txt\n\nbwhiizzzbwhuiiizzzz\n\nfoo.md\n\n- foo\n\n", + }, + } + + for _, tt := range tests { + reg := &httpmock.Registry{} + if tt.gist == nil { + reg.Register(httpmock.REST("GET", "gists/1234"), + httpmock.StatusStringResponse(404, "Not Found")) + } else { + reg.Register(httpmock.REST("GET", "gists/1234"), + httpmock.JSONResponse(tt.gist)) + } + + if tt.opts == nil { + tt.opts = &ViewOptions{} + } + + tt.opts.HttpClient = func() (*http.Client, error) { + return &http.Client{Transport: reg}, nil + } + io, _, stdout, _ := iostreams.Test() + io.SetStdoutTTY(true) + tt.opts.IO = io + + tt.opts.Selector = "1234" + + t.Run(tt.name, func(t *testing.T) { + err := viewRun(tt.opts) + if tt.wantErr { + assert.Error(t, err) + return + } + assert.NoError(t, err) + + assert.Equal(t, tt.wantOut, stdout.String()) + reg.Verify(t) + }) + } +}