Skip to content

Commit 13bbc8c

Browse files
author
Jan Sternagel
committed
added unit tests
1 parent 84541d6 commit 13bbc8c

File tree

23 files changed

+4411
-26
lines changed

23 files changed

+4411
-26
lines changed

internal/cmd/beta/kms/key/create/create.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ type inputModel struct {
4040
Backend string // Keep "backend" as a variable, but set the default to "software" (see UI)
4141
Description *string
4242
Name *string
43-
ImportOnly *bool // Default false
43+
ImportOnly bool // Default false
4444
Purpose *string
4545
}
4646

@@ -119,7 +119,7 @@ func parseInput(p *print.Printer, cmd *cobra.Command) (*inputModel, error) {
119119
Backend: flags.FlagWithDefaultToStringValue(p, cmd, backendFlag),
120120
Name: flags.FlagToStringPointer(p, cmd, displayNameFlag),
121121
Description: flags.FlagToStringPointer(p, cmd, descriptionFlag),
122-
ImportOnly: flags.FlagToBoolPointer(p, cmd, importOnlyFlag),
122+
ImportOnly: flags.FlagToBoolValue(p, cmd, importOnlyFlag),
123123
Purpose: flags.FlagToStringPointer(p, cmd, purposeFlag),
124124
}
125125

@@ -149,7 +149,7 @@ func buildRequest(ctx context.Context, model *inputModel, apiClient kmsKeyClient
149149
Algorithm: kms.CreateKeyPayloadGetAlgorithmAttributeType(model.Algorithm),
150150
Backend: kms.CreateKeyPayloadGetBackendAttributeType(&model.Backend),
151151
Purpose: kms.CreateKeyPayloadGetPurposeAttributeType(model.Purpose),
152-
ImportOnly: model.ImportOnly,
152+
ImportOnly: &model.ImportOnly,
153153
})
154154
return req, nil
155155
}
Lines changed: 323 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,323 @@
1+
package create
2+
3+
import (
4+
"context"
5+
"testing"
6+
7+
"github.com/google/go-cmp/cmp"
8+
"github.com/google/go-cmp/cmp/cmpopts"
9+
"github.com/google/uuid"
10+
"github.com/spf13/cobra"
11+
"github.com/stackitcloud/stackit-cli/internal/cmd/params"
12+
"github.com/stackitcloud/stackit-cli/internal/pkg/globalflags"
13+
"github.com/stackitcloud/stackit-cli/internal/pkg/print"
14+
"github.com/stackitcloud/stackit-cli/internal/pkg/utils"
15+
"github.com/stackitcloud/stackit-sdk-go/services/kms"
16+
)
17+
18+
const (
19+
testRegion = "eu01"
20+
)
21+
22+
type testCtxKey struct{}
23+
24+
var (
25+
testCtx = context.WithValue(context.Background(), testCtxKey{}, "foo")
26+
testClient = &kms.APIClient{}
27+
testProjectId = uuid.NewString()
28+
testKeyRingId = uuid.NewString()
29+
testAlgorithm = "some_rsa_2048"
30+
testDisplayName = "my-key"
31+
testPurpose = "asymmetric_encrypt_decrypt"
32+
testDescription = "my key description"
33+
testImportOnly = "true"
34+
testBackend = "notSoftware"
35+
)
36+
37+
// Flags
38+
func fixtureFlagValues(mods ...func(flagValues map[string]string)) map[string]string {
39+
flagValues := map[string]string{
40+
globalflags.ProjectIdFlag: testProjectId,
41+
globalflags.RegionFlag: testRegion,
42+
keyRingIdFlag: testKeyRingId,
43+
algorithmFlag: testAlgorithm,
44+
displayNameFlag: testDisplayName,
45+
purposeFlag: testPurpose,
46+
descriptionFlag: testDescription,
47+
importOnlyFlag: testImportOnly,
48+
backendFlag: testBackend,
49+
}
50+
for _, mod := range mods {
51+
mod(flagValues)
52+
}
53+
return flagValues
54+
}
55+
56+
// Input Model
57+
func fixtureInputModel(mods ...func(model *inputModel)) *inputModel {
58+
model := &inputModel{
59+
GlobalFlagModel: &globalflags.GlobalFlagModel{
60+
ProjectId: testProjectId,
61+
Region: testRegion,
62+
Verbosity: globalflags.VerbosityDefault,
63+
},
64+
KeyRingId: testKeyRingId,
65+
Algorithm: utils.Ptr(testAlgorithm),
66+
Name: utils.Ptr(testDisplayName),
67+
Purpose: utils.Ptr(testPurpose),
68+
Description: utils.Ptr(testDescription),
69+
ImportOnly: true, // Watch out: ImportOnly is not testImportOnly!
70+
Backend: testBackend,
71+
}
72+
for _, mod := range mods {
73+
mod(model)
74+
}
75+
return model
76+
}
77+
78+
// Request
79+
func fixtureRequest(mods ...func(request *kms.ApiCreateKeyRequest)) kms.ApiCreateKeyRequest {
80+
request := testClient.CreateKey(testCtx, testProjectId, testRegion, testKeyRingId)
81+
request = request.CreateKeyPayload(kms.CreateKeyPayload{
82+
Algorithm: kms.CreateKeyPayloadGetAlgorithmAttributeType(utils.Ptr(testAlgorithm)),
83+
DisplayName: utils.Ptr(testDisplayName),
84+
Purpose: kms.CreateKeyPayloadGetPurposeAttributeType(utils.Ptr(testPurpose)),
85+
Description: utils.Ptr(testDescription),
86+
ImportOnly: utils.Ptr(true),
87+
Backend: kms.CreateKeyPayloadGetBackendAttributeType(utils.Ptr(testBackend)),
88+
})
89+
90+
for _, mod := range mods {
91+
mod(&request)
92+
}
93+
return request
94+
}
95+
96+
func TestParseInput(t *testing.T) {
97+
tests := []struct {
98+
description string
99+
flagValues map[string]string
100+
isValid bool
101+
expectedModel *inputModel
102+
}{
103+
{
104+
description: "base",
105+
flagValues: fixtureFlagValues(),
106+
isValid: true,
107+
expectedModel: fixtureInputModel(),
108+
},
109+
{
110+
description: "optional flags omitted",
111+
flagValues: fixtureFlagValues(func(flagValues map[string]string) {
112+
delete(flagValues, descriptionFlag)
113+
delete(flagValues, importOnlyFlag)
114+
delete(flagValues, backendFlag)
115+
}),
116+
isValid: true,
117+
expectedModel: fixtureInputModel(func(model *inputModel) {
118+
model.Description = nil
119+
model.ImportOnly = false
120+
model.Backend = "software"
121+
}),
122+
},
123+
{
124+
description: "no values provided",
125+
flagValues: map[string]string{},
126+
isValid: false,
127+
},
128+
{
129+
description: "project id missing",
130+
flagValues: fixtureFlagValues(func(flagValues map[string]string) {
131+
delete(flagValues, globalflags.ProjectIdFlag)
132+
}),
133+
isValid: false,
134+
},
135+
{
136+
description: "project id invalid 1",
137+
flagValues: fixtureFlagValues(func(flagValues map[string]string) {
138+
flagValues[globalflags.ProjectIdFlag] = ""
139+
}),
140+
isValid: false,
141+
},
142+
{
143+
description: "project id invalid 2",
144+
flagValues: fixtureFlagValues(func(flagValues map[string]string) {
145+
flagValues[globalflags.ProjectIdFlag] = "invalid-uuid"
146+
}),
147+
isValid: false,
148+
},
149+
{
150+
description: "key ring id missing (required)",
151+
flagValues: fixtureFlagValues(func(flagValues map[string]string) {
152+
delete(flagValues, keyRingIdFlag)
153+
}),
154+
isValid: false,
155+
},
156+
{
157+
description: "key ring id invalid",
158+
flagValues: fixtureFlagValues(func(flagValues map[string]string) {
159+
flagValues[keyRingIdFlag] = "invalid-uuid"
160+
}),
161+
isValid: false,
162+
},
163+
{
164+
description: "algorithm missing (required)",
165+
flagValues: fixtureFlagValues(func(flagValues map[string]string) {
166+
delete(flagValues, algorithmFlag)
167+
}),
168+
isValid: false,
169+
},
170+
{
171+
description: "name missing (required)",
172+
flagValues: fixtureFlagValues(func(flagValues map[string]string) {
173+
delete(flagValues, displayNameFlag)
174+
}),
175+
isValid: false,
176+
},
177+
{
178+
description: "purpose missing (required)",
179+
flagValues: fixtureFlagValues(func(flagValues map[string]string) {
180+
delete(flagValues, purposeFlag)
181+
}),
182+
isValid: false,
183+
},
184+
}
185+
186+
for _, tt := range tests {
187+
t.Run(tt.description, func(t *testing.T) {
188+
cmd := &cobra.Command{}
189+
err := globalflags.Configure(cmd.Flags())
190+
if err != nil {
191+
t.Fatalf("configure global flags: %v", err)
192+
}
193+
194+
configureFlags(cmd)
195+
196+
for flag, value := range tt.flagValues {
197+
err := cmd.Flags().Set(flag, value)
198+
if err != nil {
199+
if !tt.isValid {
200+
return
201+
}
202+
t.Fatalf("setting flag --%s=%s: %v", flag, value, err)
203+
}
204+
}
205+
206+
err = cmd.ValidateRequiredFlags()
207+
if err != nil {
208+
if !tt.isValid {
209+
return
210+
}
211+
t.Fatalf("error validating flags: %v", err)
212+
}
213+
214+
p := print.NewPrinter()
215+
model, err := parseInput(p, cmd)
216+
if err != nil {
217+
if !tt.isValid {
218+
return
219+
}
220+
t.Fatalf("error parsing flags: %v", err)
221+
}
222+
223+
if !tt.isValid {
224+
t.Fatalf("did not fail on invalid input")
225+
}
226+
diff := cmp.Diff(tt.expectedModel, model)
227+
if diff != "" {
228+
t.Fatalf("Data does not match: %s", diff)
229+
}
230+
})
231+
}
232+
}
233+
234+
func TestBuildRequest(t *testing.T) {
235+
tests := []struct {
236+
description string
237+
model *inputModel
238+
expectedRequest kms.ApiCreateKeyRequest
239+
}{
240+
{
241+
description: "base case",
242+
model: fixtureInputModel(),
243+
expectedRequest: fixtureRequest(),
244+
},
245+
{
246+
description: "no optional values",
247+
model: fixtureInputModel(func(model *inputModel) {
248+
model.Description = nil
249+
model.ImportOnly = false
250+
}),
251+
expectedRequest: fixtureRequest().CreateKeyPayload(kms.CreateKeyPayload{
252+
Algorithm: kms.CreateKeyPayloadGetAlgorithmAttributeType(utils.Ptr(testAlgorithm)),
253+
DisplayName: utils.Ptr(testDisplayName),
254+
Purpose: kms.CreateKeyPayloadGetPurposeAttributeType(utils.Ptr(testPurpose)),
255+
Description: nil,
256+
ImportOnly: utils.Ptr(false),
257+
Backend: kms.CreateKeyPayloadGetBackendAttributeType(utils.Ptr(testBackend)),
258+
}),
259+
},
260+
}
261+
262+
for _, tt := range tests {
263+
t.Run(tt.description, func(t *testing.T) {
264+
request, err := buildRequest(testCtx, tt.model, testClient)
265+
if err != nil {
266+
t.Fatalf("error building request: %v", err)
267+
}
268+
269+
diff := cmp.Diff(tt.expectedRequest, request,
270+
cmp.AllowUnexported(tt.expectedRequest),
271+
cmpopts.EquateComparable(testCtx),
272+
)
273+
if diff != "" {
274+
t.Fatalf("Data does not match: %s", diff)
275+
}
276+
})
277+
}
278+
}
279+
280+
func TestOutputResult(t *testing.T) {
281+
tests := []struct {
282+
description string
283+
key *kms.Key
284+
outputFormat string
285+
projectLabel string
286+
wantErr bool
287+
}{
288+
{
289+
description: "nil response",
290+
key: nil,
291+
wantErr: true,
292+
},
293+
{
294+
description: "default output",
295+
key: &kms.Key{},
296+
projectLabel: "my-project",
297+
wantErr: false,
298+
},
299+
{
300+
description: "json output",
301+
key: &kms.Key{},
302+
outputFormat: print.JSONOutputFormat,
303+
wantErr: false,
304+
},
305+
{
306+
description: "yaml output",
307+
key: &kms.Key{},
308+
outputFormat: print.YAMLOutputFormat,
309+
wantErr: false,
310+
},
311+
}
312+
313+
p := print.NewPrinter()
314+
p.Cmd = NewCmd(&params.CmdParams{Printer: p})
315+
for _, tt := range tests {
316+
t.Run(tt.description, func(t *testing.T) {
317+
err := outputResult(p, tt.outputFormat, tt.projectLabel, tt.key)
318+
if (err != nil) != tt.wantErr {
319+
t.Errorf("outputResult() error = %v, wantErr %v", err, tt.wantErr)
320+
}
321+
})
322+
}
323+
}

0 commit comments

Comments
 (0)