1 package cmdx
2
3 import (
4 "bytes"
5 "fmt"
6 "strconv"
7 "testing"
8
9 "github.com/spf13/cobra"
10
11 "github.com/ory/x/stringslice"
12
13 "github.com/spf13/pflag"
14 "github.com/stretchr/testify/assert"
15 "github.com/stretchr/testify/require"
16 )
17
18 type (
19 dynamicTable struct {
20 t [][]string
21 cs int
22 }
23 dynamicIDAbleTable struct {
24 *dynamicTable
25 idColumn int
26 }
27 dynamicRow []string
28 dynamicIDAbleRow struct {
29 dynamicRow
30 idColumn int
31 }
32 )
33
34 var (
35 _ Table = (*dynamicTable)(nil)
36 _ Table = (*dynamicIDAbleTable)(nil)
37 _ TableRow = (dynamicRow)(nil)
38 _ TableRow = (*dynamicIDAbleRow)(nil)
39 )
40
41 func dynamicHeader(l int) []string {
42 h := make([]string, l)
43 for i := range h {
44 h[i] = "C" + strconv.Itoa(i)
45 }
46 return h
47 }
48
49 func (d *dynamicTable) Header() []string {
50 return dynamicHeader(d.cs)
51 }
52
53 func (d *dynamicTable) Table() [][]string {
54 return d.t
55 }
56
57 func (d *dynamicTable) Interface() interface{} {
58 return d.t
59 }
60
61 func (d *dynamicIDAbleTable) IDs() []string {
62 ids := make([]string, d.Len())
63 for i, row := range d.Table() {
64 ids[i] = row[d.idColumn]
65 }
66 return ids
67 }
68
69 func (d *dynamicTable) Len() int {
70 return len(d.t)
71 }
72
73 func (d dynamicRow) Header() []string {
74 return dynamicHeader(len(d))
75 }
76
77 func (d dynamicRow) Columns() []string {
78 return d
79 }
80
81 func (d dynamicRow) Interface() interface{} {
82 return d
83 }
84
85 func (d *dynamicIDAbleRow) ID() string {
86 return d.dynamicRow[d.idColumn]
87 }
88
89 func TestPrinting(t *testing.T) {
90 t.Run("case=format flags", func(t *testing.T) {
91 t.Run("format=no value", func(t *testing.T) {
92 flags := pflag.NewFlagSet("test flags", pflag.ContinueOnError)
93 RegisterFormatFlags(flags)
94
95 require.NoError(t, flags.Parse([]string{}))
96 f, err := flags.GetString(FlagFormat)
97 require.NoError(t, err)
98
99 assert.Equal(t, FormatDefault, format(f))
100 })
101 })
102
103 t.Run("method=table row", func(t *testing.T) {
104 t.Run("case=all formats", func(t *testing.T) {
105 tr := dynamicRow{"0", "1", "2"}
106 allFields := append(tr.Header(), tr...)
107
108 for _, tc := range []struct {
109 fArgs []string
110 contained []string
111 }{
112 {
113 fArgs: []string{"--" + FlagFormat, string(FormatTable)},
114 contained: allFields,
115 },
116 {
117 fArgs: []string{"--" + FlagQuiet},
118 contained: []string{tr[0]},
119 },
120 {
121 fArgs: []string{"--" + FlagFormat, string(FormatJSON)},
122 contained: tr,
123 },
124 {
125 fArgs: []string{"--" + FlagFormat, string(FormatJSONPretty)},
126 contained: tr,
127 },
128 } {
129 t.Run(fmt.Sprintf("format=%v", tc.fArgs), func(t *testing.T) {
130 cmd := &cobra.Command{Use: "x"}
131 RegisterFormatFlags(cmd.Flags())
132
133 out := &bytes.Buffer{}
134 cmd.SetOut(out)
135 require.NoError(t, cmd.Flags().Parse(tc.fArgs))
136
137 PrintRow(cmd, tr)
138
139 for _, s := range tc.contained {
140 assert.Contains(t, out.String(), s, "%s", out.String())
141 }
142 notContained := stringslice.Filter(allFields, func(s string) bool {
143 return stringslice.Has(tc.contained, s)
144 })
145 for _, s := range notContained {
146 assert.NotContains(t, out.String(), s, "%s", out.String())
147 }
148
149 assert.Equal(t, "\n", out.String()[len(out.String())-1:])
150 })
151 }
152 })
153
154 t.Run("case=uses ID()", func(t *testing.T) {
155 tr := &dynamicIDAbleRow{
156 dynamicRow: []string{"foo", "bar"},
157 idColumn: 1,
158 }
159
160 cmd := &cobra.Command{Use: "x"}
161 RegisterFormatFlags(cmd.Flags())
162
163 out := &bytes.Buffer{}
164 cmd.SetOut(out)
165 require.NoError(t, cmd.Flags().Parse([]string{"--" + FlagQuiet}))
166
167 PrintRow(cmd, tr)
168
169 assert.Equal(t, tr.dynamicRow[1]+"\n", out.String())
170 })
171 })
172
173 t.Run("method=table", func(t *testing.T) {
174 t.Run("case=full table", func(t *testing.T) {
175 tb := &dynamicTable{
176 t: [][]string{
177 {"a0", "b0", "c0"},
178 {"a1", "b1", "c1"},
179 },
180 cs: 3,
181 }
182 allFields := append(tb.Header(), append(tb.t[0], tb.t[1]...)...)
183
184 for _, tc := range []struct {
185 fArgs []string
186 contained []string
187 }{
188 {
189 fArgs: []string{"--" + FlagFormat, string(FormatTable)},
190 contained: allFields,
191 },
192 {
193 fArgs: []string{"--" + FlagQuiet},
194 contained: []string{tb.t[0][0], tb.t[1][0]},
195 },
196 {
197 fArgs: []string{"--" + FlagFormat, string(FormatJSON)},
198 contained: append(tb.t[0], tb.t[1]...),
199 },
200 {
201 fArgs: []string{"--" + FlagFormat, string(FormatJSONPretty)},
202 contained: append(tb.t[0], tb.t[1]...),
203 },
204 } {
205 t.Run(fmt.Sprintf("format=%v", tc.fArgs), func(t *testing.T) {
206 cmd := &cobra.Command{Use: "x"}
207 RegisterFormatFlags(cmd.Flags())
208
209 out := &bytes.Buffer{}
210 cmd.SetOut(out)
211 require.NoError(t, cmd.Flags().Parse(tc.fArgs))
212
213 PrintTable(cmd, tb)
214
215 for _, s := range tc.contained {
216 assert.Contains(t, out.String(), s, "%s", out.String())
217 }
218 notContained := stringslice.Filter(allFields, func(s string) bool {
219 return stringslice.Has(tc.contained, s)
220 })
221 for _, s := range notContained {
222 assert.NotContains(t, out.String(), s, "%s", out.String())
223 }
224
225 assert.Equal(t, "\n", out.String()[len(out.String())-1:])
226 })
227 }
228 })
229
230 t.Run("case=empty table", func(t *testing.T) {
231 tb := &dynamicTable{
232 t: nil,
233 cs: 1,
234 }
235
236 for _, tc := range []struct {
237 fArgs []string
238 expected string
239 }{
240 {
241 fArgs: []string{"--" + FlagFormat, string(FormatTable)},
242 expected: "C0\t",
243 },
244 {
245 fArgs: []string{"--" + FlagQuiet},
246 expected: "",
247 },
248 {
249 fArgs: []string{"--" + FlagFormat, string(FormatJSON)},
250 expected: "null",
251 },
252 {
253 fArgs: []string{"--" + FlagFormat, string(FormatJSONPretty)},
254 expected: "null",
255 },
256 } {
257 t.Run(fmt.Sprintf("format=%v", tc.fArgs), func(t *testing.T) {
258 cmd := &cobra.Command{Use: "x"}
259 RegisterFormatFlags(cmd.Flags())
260
261 out := &bytes.Buffer{}
262 cmd.SetOut(out)
263 require.NoError(t, cmd.Flags().Parse(tc.fArgs))
264
265 PrintTable(cmd, tb)
266
267 assert.Equal(t, tc.expected+"\n", out.String())
268 })
269 }
270 })
271
272 t.Run("case=uses IDs()", func(t *testing.T) {
273 tb := &dynamicIDAbleTable{
274 dynamicTable: &dynamicTable{
275 t: [][]string{
276 {"a0", "b0", "c0"},
277 {"a1", "b1", "c1"},
278 },
279 cs: 3,
280 },
281 idColumn: 1,
282 }
283 cmd := &cobra.Command{Use: "x"}
284 RegisterFormatFlags(cmd.Flags())
285
286 out := &bytes.Buffer{}
287 cmd.SetOut(out)
288 require.NoError(t, cmd.Flags().Parse([]string{"--" + FlagQuiet}))
289
290 PrintTable(cmd, tb)
291
292 assert.Equal(t, tb.t[0][1]+"\n"+tb.t[1][1]+"\n", out.String())
293 })
294 })
295 }
296
View as plain text