1package list
2
3import (
4	"bytes"
5	"fmt"
6	"io/ioutil"
7	"net/http"
8	"testing"
9	"time"
10
11	"github.com/MakeNowJust/heredoc"
12	"github.com/cli/cli/v2/internal/ghrepo"
13	"github.com/cli/cli/v2/pkg/cmdutil"
14	"github.com/cli/cli/v2/pkg/httpmock"
15	"github.com/cli/cli/v2/pkg/iostreams"
16	"github.com/google/shlex"
17	"github.com/stretchr/testify/assert"
18	"github.com/stretchr/testify/require"
19)
20
21func Test_NewCmdList(t *testing.T) {
22	tests := []struct {
23		name    string
24		args    string
25		isTTY   bool
26		want    ListOptions
27		wantErr string
28	}{
29		{
30			name:  "no arguments",
31			args:  "",
32			isTTY: true,
33			want: ListOptions{
34				LimitResults: 30,
35			},
36		},
37	}
38	for _, tt := range tests {
39		t.Run(tt.name, func(t *testing.T) {
40			io, _, _, _ := iostreams.Test()
41			io.SetStdoutTTY(tt.isTTY)
42			io.SetStdinTTY(tt.isTTY)
43			io.SetStderrTTY(tt.isTTY)
44
45			f := &cmdutil.Factory{
46				IOStreams: io,
47			}
48
49			var opts *ListOptions
50			cmd := NewCmdList(f, func(o *ListOptions) error {
51				opts = o
52				return nil
53			})
54			cmd.PersistentFlags().StringP("repo", "R", "", "")
55
56			argv, err := shlex.Split(tt.args)
57			require.NoError(t, err)
58			cmd.SetArgs(argv)
59
60			cmd.SetIn(&bytes.Buffer{})
61			cmd.SetOut(ioutil.Discard)
62			cmd.SetErr(ioutil.Discard)
63
64			_, err = cmd.ExecuteC()
65			if tt.wantErr != "" {
66				require.EqualError(t, err, tt.wantErr)
67				return
68			} else {
69				require.NoError(t, err)
70			}
71
72			assert.Equal(t, tt.want.LimitResults, opts.LimitResults)
73		})
74	}
75}
76
77func Test_listRun(t *testing.T) {
78	frozenTime, err := time.Parse(time.RFC3339, "2020-08-31T15:44:24+02:00")
79	require.NoError(t, err)
80
81	tests := []struct {
82		name       string
83		isTTY      bool
84		opts       ListOptions
85		wantErr    string
86		wantStdout string
87		wantStderr string
88	}{
89		{
90			name:  "list releases",
91			isTTY: true,
92			opts: ListOptions{
93				LimitResults: 30,
94			},
95			wantStdout: heredoc.Doc(`
96				v1.1.0                 Draft        (v1.1.0)        about 1 day ago
97				The big 1.0            Latest       (v1.0.0)        about 1 day ago
98				1.0 release candidate  Pre-release  (v1.0.0-pre.2)  about 1 day ago
99				New features                        (v0.9.2)        about 1 day ago
100			`),
101			wantStderr: ``,
102		},
103		{
104			name:  "machine-readable",
105			isTTY: false,
106			opts: ListOptions{
107				LimitResults: 30,
108			},
109			wantStdout: heredoc.Doc(`
110				v1.1.0	Draft	v1.1.0	2020-08-31T15:44:24+02:00
111				The big 1.0	Latest	v1.0.0	2020-08-31T15:44:24+02:00
112				1.0 release candidate	Pre-release	v1.0.0-pre.2	2020-08-31T15:44:24+02:00
113				New features		v0.9.2	2020-08-31T15:44:24+02:00
114			`),
115			wantStderr: ``,
116		},
117	}
118	for _, tt := range tests {
119		t.Run(tt.name, func(t *testing.T) {
120			io, _, stdout, stderr := iostreams.Test()
121			io.SetStdoutTTY(tt.isTTY)
122			io.SetStdinTTY(tt.isTTY)
123			io.SetStderrTTY(tt.isTTY)
124
125			createdAt := frozenTime
126			if tt.isTTY {
127				createdAt = time.Now().Add(time.Duration(-24) * time.Hour)
128			}
129
130			fakeHTTP := &httpmock.Registry{}
131			fakeHTTP.Register(httpmock.GraphQL(`\bRepositoryReleaseList\(`), httpmock.StringResponse(fmt.Sprintf(`
132			{ "data": { "repository": { "releases": {
133				"nodes": [
134					{
135						"name": "",
136						"tagName": "v1.1.0",
137						"isDraft": true,
138						"isPrerelease": false,
139						"createdAt": "%[1]s",
140						"publishedAt": "%[1]s"
141					},
142					{
143						"name": "The big 1.0",
144						"tagName": "v1.0.0",
145						"isDraft": false,
146						"isPrerelease": false,
147						"createdAt": "%[1]s",
148						"publishedAt": "%[1]s"
149					},
150					{
151						"name": "1.0 release candidate",
152						"tagName": "v1.0.0-pre.2",
153						"isDraft": false,
154						"isPrerelease": true,
155						"createdAt": "%[1]s",
156						"publishedAt": "%[1]s"
157					},
158					{
159						"name": "New features",
160						"tagName": "v0.9.2",
161						"isDraft": false,
162						"isPrerelease": false,
163						"createdAt": "%[1]s",
164						"publishedAt": "%[1]s"
165					}
166				]
167			} } } }`, createdAt.Format(time.RFC3339))))
168
169			tt.opts.IO = io
170			tt.opts.HttpClient = func() (*http.Client, error) {
171				return &http.Client{Transport: fakeHTTP}, nil
172			}
173			tt.opts.BaseRepo = func() (ghrepo.Interface, error) {
174				return ghrepo.FromFullName("OWNER/REPO")
175			}
176
177			err := listRun(&tt.opts)
178			if tt.wantErr != "" {
179				require.EqualError(t, err, tt.wantErr)
180				return
181			} else {
182				require.NoError(t, err)
183			}
184
185			assert.Equal(t, tt.wantStdout, stdout.String())
186			assert.Equal(t, tt.wantStderr, stderr.String())
187		})
188	}
189}
190