diff --git a/pkg/cmd/release/delete/delete_test.go b/pkg/cmd/release/delete/delete_test.go new file mode 100644 index 000000000..87c27adc6 --- /dev/null +++ b/pkg/cmd/release/delete/delete_test.go @@ -0,0 +1,160 @@ +package delete + +import ( + "bytes" + "io/ioutil" + "net/http" + "testing" + + "github.com/MakeNowJust/heredoc" + "github.com/cli/cli/internal/ghrepo" + "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" + "github.com/stretchr/testify/require" +) + +func Test_NewCmdReady(t *testing.T) { + tests := []struct { + name string + args string + isTTY bool + want DeleteOptions + wantErr string + }{ + { + name: "number argument", + args: "v1.2.3", + isTTY: true, + want: DeleteOptions{ + TagName: "v1.2.3", + SkipConfirm: false, + }, + }, + { + name: "skip confirm", + args: "v1.2.3 -y", + isTTY: true, + want: DeleteOptions{ + TagName: "v1.2.3", + SkipConfirm: true, + }, + }, + { + name: "no arguments", + args: "", + isTTY: true, + wantErr: "accepts 1 arg(s), received 0", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + io, _, _, _ := iostreams.Test() + io.SetStdoutTTY(tt.isTTY) + io.SetStdinTTY(tt.isTTY) + io.SetStderrTTY(tt.isTTY) + + f := &cmdutil.Factory{ + IOStreams: io, + } + + var opts *DeleteOptions + cmd := NewCmdDelete(f, func(o *DeleteOptions) error { + opts = o + return nil + }) + cmd.PersistentFlags().StringP("repo", "R", "", "") + + argv, err := shlex.Split(tt.args) + require.NoError(t, err) + cmd.SetArgs(argv) + + cmd.SetIn(&bytes.Buffer{}) + cmd.SetOut(ioutil.Discard) + cmd.SetErr(ioutil.Discard) + + _, err = cmd.ExecuteC() + if tt.wantErr != "" { + require.EqualError(t, err, tt.wantErr) + return + } else { + require.NoError(t, err) + } + + assert.Equal(t, tt.want.TagName, opts.TagName) + assert.Equal(t, tt.want.SkipConfirm, opts.SkipConfirm) + }) + } +} + +func Test_deleteRun(t *testing.T) { + tests := []struct { + name string + isTTY bool + opts DeleteOptions + wantErr string + wantStdout string + wantStderr string + }{ + { + name: "skipping confirmation", + isTTY: true, + opts: DeleteOptions{ + TagName: "v1.2.3", + SkipConfirm: true, + }, + wantStdout: ``, + wantStderr: heredoc.Doc(` + ✓ Deleted release v1.2.3 + ! Note that the v1.2.3 git tag still remains in the repository + `), + }, + { + name: "non-interactive", + isTTY: false, + opts: DeleteOptions{ + TagName: "v1.2.3", + SkipConfirm: false, + }, + wantStdout: ``, + wantStderr: ``, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + io, _, stdout, stderr := iostreams.Test() + io.SetStdoutTTY(tt.isTTY) + io.SetStdinTTY(tt.isTTY) + io.SetStderrTTY(tt.isTTY) + + fakeHTTP := &httpmock.Registry{} + fakeHTTP.Register(httpmock.REST("GET", "repos/OWNER/REPO/releases/tags/v1.2.3"), httpmock.StringResponse(`{ + "tag_name": "v1.2.3", + "draft": false, + "url": "https://api.github.com/repos/OWNER/REPO/releases/23456" + }`)) + fakeHTTP.Register(httpmock.REST("DELETE", "repos/OWNER/REPO/releases/23456"), httpmock.StatusStringResponse(204, "")) + + tt.opts.IO = io + tt.opts.HttpClient = func() (*http.Client, error) { + return &http.Client{Transport: fakeHTTP}, nil + } + tt.opts.BaseRepo = func() (ghrepo.Interface, error) { + return ghrepo.FromFullName("OWNER/REPO") + } + + err := deleteRun(&tt.opts) + if tt.wantErr != "" { + require.EqualError(t, err, tt.wantErr) + return + } else { + require.NoError(t, err) + } + + assert.Equal(t, tt.wantStdout, stdout.String()) + assert.Equal(t, tt.wantStderr, stderr.String()) + }) + } +} diff --git a/pkg/cmd/release/list/list_test.go b/pkg/cmd/release/list/list_test.go new file mode 100644 index 000000000..c6e0f6c85 --- /dev/null +++ b/pkg/cmd/release/list/list_test.go @@ -0,0 +1,169 @@ +package list + +import ( + "bytes" + "fmt" + "io/ioutil" + "net/http" + "testing" + "time" + + "github.com/MakeNowJust/heredoc" + "github.com/cli/cli/internal/ghrepo" + "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" + "github.com/stretchr/testify/require" +) + +func Test_NewCmdList(t *testing.T) { + tests := []struct { + name string + args string + isTTY bool + want ListOptions + wantErr string + }{ + { + name: "no arguments", + args: "", + isTTY: true, + want: ListOptions{ + LimitResults: 30, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + io, _, _, _ := iostreams.Test() + io.SetStdoutTTY(tt.isTTY) + io.SetStdinTTY(tt.isTTY) + io.SetStderrTTY(tt.isTTY) + + f := &cmdutil.Factory{ + IOStreams: io, + } + + var opts *ListOptions + cmd := NewCmdList(f, func(o *ListOptions) error { + opts = o + return nil + }) + cmd.PersistentFlags().StringP("repo", "R", "", "") + + argv, err := shlex.Split(tt.args) + require.NoError(t, err) + cmd.SetArgs(argv) + + cmd.SetIn(&bytes.Buffer{}) + cmd.SetOut(ioutil.Discard) + cmd.SetErr(ioutil.Discard) + + _, err = cmd.ExecuteC() + if tt.wantErr != "" { + require.EqualError(t, err, tt.wantErr) + return + } else { + require.NoError(t, err) + } + + assert.Equal(t, tt.want.LimitResults, opts.LimitResults) + }) + } +} + +func Test_listRun(t *testing.T) { + tests := []struct { + name string + isTTY bool + opts ListOptions + wantErr string + wantStdout string + wantStderr string + }{ + { + name: "list releases", + isTTY: true, + opts: ListOptions{ + LimitResults: 30, + }, + wantStdout: heredoc.Doc(` + v1.1.0 Draft (v1.1.0) about 1 day ago + The big 1.0 Latest (v1.0.0) about 1 day ago + 1.0 release candidate Pre-release (v1.0.0-pre.2) about 1 day ago + New features (v0.9.2) about 1 day ago + `), + wantStderr: ``, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + io, _, stdout, stderr := iostreams.Test() + io.SetStdoutTTY(tt.isTTY) + io.SetStdinTTY(tt.isTTY) + io.SetStderrTTY(tt.isTTY) + + relativeTime := time.Now().Add(time.Duration(-24) * time.Hour) + + fakeHTTP := &httpmock.Registry{} + fakeHTTP.Register(httpmock.GraphQL(`\bRepositoryReleaseList\(`), httpmock.StringResponse(fmt.Sprintf(` + { "data": { "repository": { "releases": { + "nodes": [ + { + "name": "", + "tagName": "v1.1.0", + "isDraft": true, + "isPrerelease": false, + "createdAt": "%[1]s", + "publishedAt": "%[1]s" + }, + { + "name": "The big 1.0", + "tagName": "v1.0.0", + "isDraft": false, + "isPrerelease": false, + "createdAt": "%[1]s", + "publishedAt": "%[1]s" + }, + { + "name": "1.0 release candidate", + "tagName": "v1.0.0-pre.2", + "isDraft": false, + "isPrerelease": true, + "createdAt": "%[1]s", + "publishedAt": "%[1]s" + }, + { + "name": "New features", + "tagName": "v0.9.2", + "isDraft": false, + "isPrerelease": false, + "createdAt": "%[1]s", + "publishedAt": "%[1]s" + } + ] + } } } }`, relativeTime.Format(time.RFC3339)))) + + tt.opts.IO = io + tt.opts.HttpClient = func() (*http.Client, error) { + return &http.Client{Transport: fakeHTTP}, nil + } + tt.opts.BaseRepo = func() (ghrepo.Interface, error) { + return ghrepo.FromFullName("OWNER/REPO") + } + + err := listRun(&tt.opts) + if tt.wantErr != "" { + require.EqualError(t, err, tt.wantErr) + return + } else { + require.NoError(t, err) + } + + assert.Equal(t, tt.wantStdout, stdout.String()) + assert.Equal(t, tt.wantStderr, stderr.String()) + }) + } +} diff --git a/pkg/iostreams/color.go b/pkg/iostreams/color.go index ed4b32a8f..6bbc429c5 100644 --- a/pkg/iostreams/color.go +++ b/pkg/iostreams/color.go @@ -82,5 +82,5 @@ func (c *ColorScheme) SuccessIcon() string { } func (c *ColorScheme) WarningIcon() string { - return c.Yellow("✓") + return c.Yellow("!") } diff --git a/pkg/iostreams/iostreams.go b/pkg/iostreams/iostreams.go index aa119164f..a5164e32d 100644 --- a/pkg/iostreams/iostreams.go +++ b/pkg/iostreams/iostreams.go @@ -129,7 +129,7 @@ func (s *IOStreams) TerminalWidth() int { } func (s *IOStreams) ColorScheme() *ColorScheme { - return NewColorScheme(s.IsStdoutTTY()) + return NewColorScheme(s.ColorEnabled()) } func System() *IOStreams {