Skip to content

Commit 1ced0ce

Browse files
committed
chore: add more output format tests
1 parent 1ad2a4c commit 1ced0ce

File tree

2 files changed

+131
-0
lines changed

2 files changed

+131
-0
lines changed

cli/cliui/output.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ func NewOutputFormatter(formats ...OutputFormat) *OutputFormatter {
3030

3131
formatIDs := make(map[string]struct{}, len(formats))
3232
for _, format := range formats {
33+
if format.ID() == "" {
34+
panic("output format ID must not be empty")
35+
}
3336
if _, ok := formatIDs[format.ID()]; ok {
3437
panic("duplicate format ID: " + format.ID())
3538
}

cli/cliui/output_test.go

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
package cliui_test
2+
3+
import (
4+
"context"
5+
"encoding/json"
6+
"sync/atomic"
7+
"testing"
8+
9+
"github.com/spf13/cobra"
10+
"github.com/stretchr/testify/require"
11+
12+
"github.com/coder/coder/cli/cliui"
13+
)
14+
15+
type format struct {
16+
id string
17+
attachFlagsFn func(cmd *cobra.Command)
18+
formatFn func(ctx context.Context, data any) (string, error)
19+
}
20+
21+
var _ cliui.OutputFormat = &format{}
22+
23+
func (f *format) ID() string {
24+
return f.id
25+
}
26+
27+
func (f *format) AttachFlags(cmd *cobra.Command) {
28+
if f.attachFlagsFn != nil {
29+
f.attachFlagsFn(cmd)
30+
}
31+
}
32+
33+
func (f *format) Format(ctx context.Context, data any) (string, error) {
34+
if f.formatFn != nil {
35+
return f.formatFn(ctx, data)
36+
}
37+
38+
return "", nil
39+
}
40+
41+
func Test_OutputFormatter(t *testing.T) {
42+
t.Parallel()
43+
44+
t.Run("RequiresTwoFormatters", func(t *testing.T) {
45+
t.Parallel()
46+
47+
require.Panics(t, func() {
48+
cliui.NewOutputFormatter()
49+
})
50+
require.Panics(t, func() {
51+
cliui.NewOutputFormatter(cliui.JSONFormat())
52+
})
53+
})
54+
55+
t.Run("NoMissingFormatID", func(t *testing.T) {
56+
t.Parallel()
57+
58+
require.Panics(t, func() {
59+
cliui.NewOutputFormatter(
60+
cliui.JSONFormat(),
61+
&format{id: ""},
62+
)
63+
})
64+
})
65+
66+
t.Run("NoDuplicateFormats", func(t *testing.T) {
67+
t.Parallel()
68+
69+
require.Panics(t, func() {
70+
cliui.NewOutputFormatter(
71+
cliui.JSONFormat(),
72+
cliui.JSONFormat(),
73+
)
74+
})
75+
})
76+
77+
t.Run("OK", func(t *testing.T) {
78+
t.Parallel()
79+
80+
var called int64
81+
f := cliui.NewOutputFormatter(
82+
cliui.JSONFormat(),
83+
&format{
84+
id: "foo",
85+
attachFlagsFn: func(cmd *cobra.Command) {
86+
cmd.Flags().StringP("foo", "f", "", "foo flag 1234")
87+
},
88+
formatFn: func(_ context.Context, _ any) (string, error) {
89+
atomic.AddInt64(&called, 1)
90+
return "foo", nil
91+
},
92+
},
93+
)
94+
95+
cmd := &cobra.Command{}
96+
f.AttachFlags(cmd)
97+
98+
selected, err := cmd.Flags().GetString("output")
99+
require.NoError(t, err)
100+
require.Equal(t, "json", selected)
101+
usage := cmd.Flags().FlagUsages()
102+
require.Contains(t, usage, "Available formats: json, foo")
103+
require.Contains(t, usage, "foo flag 1234")
104+
105+
ctx := context.Background()
106+
data := []string{"hi", "dean", "was", "here"}
107+
out, err := f.Format(ctx, data)
108+
require.NoError(t, err)
109+
110+
var got []string
111+
require.NoError(t, json.Unmarshal([]byte(out), &got))
112+
require.Equal(t, data, got)
113+
require.EqualValues(t, 0, atomic.LoadInt64(&called))
114+
115+
require.NoError(t, cmd.Flags().Set("output", "foo"))
116+
out, err = f.Format(ctx, data)
117+
require.NoError(t, err)
118+
require.Equal(t, "foo", out)
119+
require.EqualValues(t, 1, atomic.LoadInt64(&called))
120+
121+
require.NoError(t, cmd.Flags().Set("output", "bar"))
122+
out, err = f.Format(ctx, data)
123+
require.Error(t, err)
124+
require.ErrorContains(t, err, "bar")
125+
require.Equal(t, "", out)
126+
require.EqualValues(t, 1, atomic.LoadInt64(&called))
127+
})
128+
}

0 commit comments

Comments
 (0)