forked from stackitcloud/stackit-cli
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtestutils.go
More file actions
138 lines (119 loc) · 3.99 KB
/
Copy pathtestutils.go
File metadata and controls
138 lines (119 loc) · 3.99 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
package testutils
import (
"testing"
"github.com/spf13/pflag"
"github.com/stackitcloud/stackit-cli/internal/pkg/testparams"
"github.com/stackitcloud/stackit-cli/internal/pkg/types"
"github.com/google/go-cmp/cmp"
"github.com/spf13/cobra"
"github.com/stackitcloud/stackit-cli/internal/pkg/globalflags"
"github.com/stackitcloud/stackit-cli/internal/pkg/print"
)
// TestParseInput centralizes the logic to test a combination of inputs (arguments, flags) for a cobra command
func TestParseInput[T any](t *testing.T, cmdFactory func(*types.CmdParams) *cobra.Command, parseInputFunc func(*print.Printer, *cobra.Command, []string) (T, error), expectedModel T, argValues []string, flagValues map[string]string, isValid bool) {
t.Helper()
TestParseInputWithAdditionalFlags(t, cmdFactory, parseInputFunc, expectedModel, argValues, flagValues, map[string][]string{}, isValid)
}
// TestParseInputWithAdditionalFlags centralizes the logic to test a combination of inputs (arguments, flags) for a cobra command.
// It allows to pass multiple instances of a single flag to the cobra command using the `additionalFlagValues` parameter.
func TestParseInputWithAdditionalFlags[T any](t *testing.T, cmdFactory func(*types.CmdParams) *cobra.Command, parseInputFunc func(*print.Printer, *cobra.Command, []string) (T, error), expectedModel T, argValues []string, flagValues map[string]string, additionalFlagValues map[string][]string, isValid bool) {
TestParseInputWithOptions(t, cmdFactory, parseInputFunc, expectedModel, argValues, flagValues, additionalFlagValues, isValid, nil)
}
type Resettable interface {
Reset()
}
func TestParseInputWithOptions[T any](t *testing.T, cmdFactory func(*types.CmdParams) *cobra.Command, parseInputFunc func(*print.Printer, *cobra.Command, []string) (T, error), expectedModel T, argValues []string, flagValues map[string]string, additionalFlagValues map[string][]string, isValid bool, testingOptions []TestingOption) {
opts := Option{}
for _, option := range testingOptions {
err := option(&opts)
if err != nil {
t.Errorf("Configuring testing options: %v", err)
return
}
}
params := testparams.NewTestParams()
cmd := cmdFactory(params.CmdParams)
err := globalflags.Configure(cmd.Flags())
if err != nil {
t.Fatalf("configure global flags: %v", err)
}
cmd.Flags().VisitAll(func(flag *pflag.Flag) {
if flag.Value == nil {
return
}
// StringEnum and StringEnumSlice Flags are stateful singletons. During tests we reset their state.
if r, ok := flag.Value.(Resettable); ok {
r.Reset()
}
})
// set regular flag values
for flag, value := range flagValues {
err := cmd.Flags().Set(flag, value)
if err != nil {
if !isValid {
return
}
t.Fatalf("setting flag --%s=%s: %v", flag, value, err)
}
}
// set additional flag values
for flag, values := range additionalFlagValues {
for _, value := range values {
err := cmd.Flags().Set(flag, value)
if err != nil {
if !isValid {
return
}
t.Fatalf("setting flag --%s=%s: %v", flag, value, err)
}
}
}
if cmd.PreRun != nil {
// can be used for dynamic flag configuration
cmd.PreRun(cmd, argValues)
}
if cmd.PreRunE != nil {
err := cmd.PreRunE(cmd, argValues)
if err != nil {
if !isValid {
return
}
t.Fatalf("error in PreRunE: %v", err)
}
}
err = cmd.ValidateArgs(argValues)
if err != nil {
if !isValid {
return
}
t.Fatalf("error validating args: %v", err)
}
err = cmd.ValidateRequiredFlags()
if err != nil {
if !isValid {
return
}
t.Fatalf("error validating flags: %v", err)
}
err = cmd.ValidateFlagGroups()
if err != nil {
if !isValid {
return
}
t.Fatalf("error validating flags: %v", err)
}
model, err := parseInputFunc(params.Printer, cmd, argValues)
if err != nil {
if !isValid {
return
}
t.Fatalf("error parsing input: %v", err)
}
if !isValid {
t.Fatalf("did not fail on invalid input")
}
diff := cmp.Diff(expectedModel, model, opts.cmpOptions...)
if diff != "" {
t.Fatalf("Data does not match (-expected, +actual): %s", diff)
}
}