github.com/fastly/cli@v1.7.2-0.20240304164155-9d0f1d77c3bf/pkg/commands/vcl/condition/condition_test.go (about) 1 package condition_test 2 3 import ( 4 "bytes" 5 "errors" 6 "io" 7 "strings" 8 "testing" 9 10 "github.com/fastly/go-fastly/v9/fastly" 11 12 "github.com/fastly/cli/pkg/app" 13 "github.com/fastly/cli/pkg/global" 14 "github.com/fastly/cli/pkg/mock" 15 "github.com/fastly/cli/pkg/testutil" 16 ) 17 18 func TestConditionCreate(t *testing.T) { 19 args := testutil.Args 20 scenarios := []testutil.TestScenario{ 21 { 22 Args: args("vcl condition create --version 1"), 23 WantError: "error reading service: no service ID found", 24 }, 25 { 26 Args: args("vcl condition create --service-id 123 --version 1 --name always_false --statement false --type REQUEST --autoclone"), 27 API: mock.API{ 28 ListVersionsFn: testutil.ListVersions, 29 CloneVersionFn: testutil.CloneVersionResult(4), 30 CreateConditionFn: createConditionOK, 31 }, 32 WantOutput: "Created condition always_false (service 123 version 4)", 33 }, 34 { 35 Args: args("vcl condition create --service-id 123 --version 1 --name always_false --statement false --type REQUEST --priority 10 --autoclone"), 36 API: mock.API{ 37 ListVersionsFn: testutil.ListVersions, 38 CloneVersionFn: testutil.CloneVersionResult(4), 39 CreateConditionFn: createConditionError, 40 }, 41 WantError: errTest.Error(), 42 }, 43 } 44 45 for _, testcase := range scenarios { 46 t.Run(testcase.Name, func(t *testing.T) { 47 var stdout bytes.Buffer 48 app.Init = func(_ []string, _ io.Reader) (*global.Data, error) { 49 opts := testutil.MockGlobalData(testcase.Args, &stdout) 50 opts.APIClientFactory = mock.APIClient(testcase.API) 51 return opts, nil 52 } 53 err := app.Run(testcase.Args, nil) 54 testutil.AssertErrorContains(t, err, testcase.WantError) 55 testutil.AssertStringContains(t, stdout.String(), testcase.WantOutput) 56 }) 57 } 58 } 59 60 func TestConditionDelete(t *testing.T) { 61 args := testutil.Args 62 scenarios := []testutil.TestScenario{ 63 { 64 Args: args("vcl condition delete --service-id 123 --version 1"), 65 WantError: "error parsing arguments: required flag --name not provided", 66 }, 67 { 68 Args: args("vcl condition delete --service-id 123 --version 1 --name always_false --autoclone"), 69 API: mock.API{ 70 ListVersionsFn: testutil.ListVersions, 71 CloneVersionFn: testutil.CloneVersionResult(4), 72 DeleteConditionFn: deleteConditionError, 73 }, 74 WantError: errTest.Error(), 75 }, 76 { 77 Args: args("vcl condition delete --service-id 123 --version 1 --name always_false --autoclone"), 78 API: mock.API{ 79 ListVersionsFn: testutil.ListVersions, 80 CloneVersionFn: testutil.CloneVersionResult(4), 81 DeleteConditionFn: deleteConditionOK, 82 }, 83 WantOutput: "Deleted condition always_false (service 123 version 4)", 84 }, 85 } 86 for testcaseIdx := range scenarios { 87 testcase := &scenarios[testcaseIdx] 88 t.Run(testcase.Name, func(t *testing.T) { 89 var stdout bytes.Buffer 90 app.Init = func(_ []string, _ io.Reader) (*global.Data, error) { 91 opts := testutil.MockGlobalData(testcase.Args, &stdout) 92 opts.APIClientFactory = mock.APIClient(testcase.API) 93 return opts, nil 94 } 95 err := app.Run(testcase.Args, nil) 96 testutil.AssertErrorContains(t, err, testcase.WantError) 97 testutil.AssertStringContains(t, stdout.String(), testcase.WantOutput) 98 }) 99 } 100 } 101 102 func TestConditionUpdate(t *testing.T) { 103 args := testutil.Args 104 scenarios := []testutil.TestScenario{ 105 { 106 Args: args("vcl condition update --service-id 123 --version 1 --new-name false_always --comment "), 107 WantError: "error parsing arguments: required flag --name not provided", 108 }, 109 { 110 Args: args("vcl condition update --service-id 123 --version 1 --name always_false --autoclone"), 111 API: mock.API{ 112 ListVersionsFn: testutil.ListVersions, 113 CloneVersionFn: testutil.CloneVersionResult(4), 114 UpdateConditionFn: updateConditionOK, 115 }, 116 WantError: "error parsing arguments: must provide either --new-name, --statement, --type or --priority to update condition", 117 }, 118 { 119 Args: args("vcl condition update --service-id 123 --version 1 --name always_false --new-name false_always --autoclone"), 120 API: mock.API{ 121 ListVersionsFn: testutil.ListVersions, 122 CloneVersionFn: testutil.CloneVersionResult(4), 123 UpdateConditionFn: updateConditionError, 124 }, 125 WantError: errTest.Error(), 126 }, 127 { 128 Args: args("vcl condition update --service-id 123 --version 1 --name always_false --new-name false_always --autoclone"), 129 API: mock.API{ 130 ListVersionsFn: testutil.ListVersions, 131 CloneVersionFn: testutil.CloneVersionResult(4), 132 UpdateConditionFn: updateConditionOK, 133 }, 134 WantOutput: "Updated condition false_always (service 123 version 4)", 135 }, 136 } 137 for testcaseIdx := range scenarios { 138 testcase := &scenarios[testcaseIdx] 139 t.Run(testcase.Name, func(t *testing.T) { 140 var stdout bytes.Buffer 141 app.Init = func(_ []string, _ io.Reader) (*global.Data, error) { 142 opts := testutil.MockGlobalData(testcase.Args, &stdout) 143 opts.APIClientFactory = mock.APIClient(testcase.API) 144 return opts, nil 145 } 146 err := app.Run(testcase.Args, nil) 147 testutil.AssertErrorContains(t, err, testcase.WantError) 148 testutil.AssertStringContains(t, stdout.String(), testcase.WantOutput) 149 }) 150 } 151 } 152 153 func TestConditionDescribe(t *testing.T) { 154 args := testutil.Args 155 scenarios := []testutil.TestScenario{ 156 { 157 Args: args("vcl condition describe --service-id 123 --version 1"), 158 WantError: "error parsing arguments: required flag --name not provided", 159 }, 160 { 161 Args: args("vcl condition describe --service-id 123 --version 1 --name always_false"), 162 API: mock.API{ 163 ListVersionsFn: testutil.ListVersions, 164 GetConditionFn: getConditionError, 165 }, 166 WantError: errTest.Error(), 167 }, 168 { 169 Args: args("vcl condition describe --service-id 123 --version 1 --name always_false"), 170 API: mock.API{ 171 ListVersionsFn: testutil.ListVersions, 172 GetConditionFn: getConditionOK, 173 }, 174 WantOutput: describeConditionOutput, 175 }, 176 } 177 for testcaseIdx := range scenarios { 178 testcase := &scenarios[testcaseIdx] 179 t.Run(testcase.Name, func(t *testing.T) { 180 var stdout bytes.Buffer 181 app.Init = func(_ []string, _ io.Reader) (*global.Data, error) { 182 opts := testutil.MockGlobalData(testcase.Args, &stdout) 183 opts.APIClientFactory = mock.APIClient(testcase.API) 184 return opts, nil 185 } 186 err := app.Run(testcase.Args, nil) 187 testutil.AssertErrorContains(t, err, testcase.WantError) 188 testutil.AssertString(t, testcase.WantOutput, stdout.String()) 189 }) 190 } 191 } 192 193 func TestConditionList(t *testing.T) { 194 args := testutil.Args 195 scenarios := []testutil.TestScenario{ 196 { 197 Args: args("vcl condition list --service-id 123 --version 1"), 198 API: mock.API{ 199 ListVersionsFn: testutil.ListVersions, 200 ListConditionsFn: listConditionsOK, 201 }, 202 WantOutput: listConditionsShortOutput, 203 }, 204 { 205 Args: args("vcl condition list --service-id 123 --version 1 --verbose"), 206 API: mock.API{ 207 ListVersionsFn: testutil.ListVersions, 208 ListConditionsFn: listConditionsOK, 209 }, 210 WantOutput: listConditionsVerboseOutput, 211 }, 212 { 213 Args: args("vcl condition list --service-id 123 --version 1 -v"), 214 API: mock.API{ 215 ListVersionsFn: testutil.ListVersions, 216 ListConditionsFn: listConditionsOK, 217 }, 218 WantOutput: listConditionsVerboseOutput, 219 }, 220 { 221 Args: args("vcl condition --verbose list --service-id 123 --version 1"), 222 API: mock.API{ 223 ListVersionsFn: testutil.ListVersions, 224 ListConditionsFn: listConditionsOK, 225 }, 226 WantOutput: listConditionsVerboseOutput, 227 }, 228 { 229 Args: args("-v vcl condition list --service-id 123 --version 1"), 230 API: mock.API{ 231 ListVersionsFn: testutil.ListVersions, 232 ListConditionsFn: listConditionsOK, 233 }, 234 WantOutput: listConditionsVerboseOutput, 235 }, 236 { 237 Args: args("vcl condition list --service-id 123 --version 1"), 238 API: mock.API{ 239 ListVersionsFn: testutil.ListVersions, 240 ListConditionsFn: listConditionsError, 241 }, 242 WantError: errTest.Error(), 243 }, 244 } 245 for testcaseIdx := range scenarios { 246 testcase := &scenarios[testcaseIdx] 247 t.Run(testcase.Name, func(t *testing.T) { 248 var stdout bytes.Buffer 249 app.Init = func(_ []string, _ io.Reader) (*global.Data, error) { 250 opts := testutil.MockGlobalData(testcase.Args, &stdout) 251 opts.APIClientFactory = mock.APIClient(testcase.API) 252 return opts, nil 253 } 254 err := app.Run(testcase.Args, nil) 255 testutil.AssertErrorContains(t, err, testcase.WantError) 256 testutil.AssertString(t, testcase.WantOutput, stdout.String()) 257 }) 258 } 259 } 260 261 var describeConditionOutput = "\n" + strings.TrimSpace(` 262 Service ID: 123 263 Version: 1 264 Name: always_false 265 Statement: false 266 Type: CACHE 267 Priority: 10 268 `) + "\n" 269 270 var listConditionsShortOutput = strings.TrimSpace(` 271 SERVICE VERSION NAME STATEMENT TYPE PRIORITY 272 123 1 always_false_request false REQUEST 10 273 123 1 always_false_cache false CACHE 10 274 `) + "\n" 275 276 var listConditionsVerboseOutput = strings.TrimSpace(` 277 Fastly API endpoint: https://api.fastly.com 278 Fastly API token provided via config file (profile: user) 279 280 Service ID (via --service-id): 123 281 282 Version: 1 283 Condition 1/2 284 Name: always_false_request 285 Statement: false 286 Type: REQUEST 287 Priority: 10 288 Condition 2/2 289 Name: always_false_cache 290 Statement: false 291 Type: CACHE 292 Priority: 10 293 `) + "\n\n" 294 295 var errTest = errors.New("fixture error") 296 297 func createConditionOK(i *fastly.CreateConditionInput) (*fastly.Condition, error) { 298 priority := 10 299 if i.Priority != nil { 300 priority = *i.Priority 301 } 302 303 conditionType := "REQUEST" 304 if i.Type != nil { 305 conditionType = *i.Type 306 } 307 308 return &fastly.Condition{ 309 ServiceID: fastly.ToPointer(i.ServiceID), 310 ServiceVersion: fastly.ToPointer(i.ServiceVersion), 311 Name: i.Name, 312 Statement: i.Statement, 313 Type: fastly.ToPointer(conditionType), 314 Priority: fastly.ToPointer(priority), 315 }, nil 316 } 317 318 func createConditionError(_ *fastly.CreateConditionInput) (*fastly.Condition, error) { 319 return nil, errTest 320 } 321 322 func deleteConditionOK(_ *fastly.DeleteConditionInput) error { 323 return nil 324 } 325 326 func deleteConditionError(_ *fastly.DeleteConditionInput) error { 327 return errTest 328 } 329 330 func updateConditionOK(i *fastly.UpdateConditionInput) (*fastly.Condition, error) { 331 priority := 10 332 if i.Priority != nil { 333 priority = *i.Priority 334 } 335 336 conditionType := "REQUEST" 337 if i.Type != nil { 338 conditionType = *i.Type 339 } 340 341 statement := "false" 342 if i.Statement != nil { 343 statement = *i.Type 344 } 345 346 return &fastly.Condition{ 347 ServiceID: fastly.ToPointer(i.ServiceID), 348 ServiceVersion: fastly.ToPointer(i.ServiceVersion), 349 Name: fastly.ToPointer(i.Name), 350 Statement: fastly.ToPointer(statement), 351 Type: fastly.ToPointer(conditionType), 352 Priority: fastly.ToPointer(priority), 353 }, nil 354 } 355 356 func updateConditionError(_ *fastly.UpdateConditionInput) (*fastly.Condition, error) { 357 return nil, errTest 358 } 359 360 func getConditionOK(i *fastly.GetConditionInput) (*fastly.Condition, error) { 361 priority := 10 362 conditionType := "CACHE" 363 statement := "false" 364 365 return &fastly.Condition{ 366 ServiceID: fastly.ToPointer(i.ServiceID), 367 ServiceVersion: fastly.ToPointer(i.ServiceVersion), 368 Name: fastly.ToPointer(i.Name), 369 Statement: fastly.ToPointer(statement), 370 Type: fastly.ToPointer(conditionType), 371 Priority: fastly.ToPointer(priority), 372 }, nil 373 } 374 375 func getConditionError(_ *fastly.GetConditionInput) (*fastly.Condition, error) { 376 return nil, errTest 377 } 378 379 func listConditionsOK(i *fastly.ListConditionsInput) ([]*fastly.Condition, error) { 380 return []*fastly.Condition{ 381 { 382 ServiceID: fastly.ToPointer(i.ServiceID), 383 ServiceVersion: fastly.ToPointer(i.ServiceVersion), 384 Name: fastly.ToPointer("always_false_request"), 385 Statement: fastly.ToPointer("false"), 386 Type: fastly.ToPointer("REQUEST"), 387 Priority: fastly.ToPointer(10), 388 }, 389 { 390 ServiceID: fastly.ToPointer(i.ServiceID), 391 ServiceVersion: fastly.ToPointer(i.ServiceVersion), 392 Name: fastly.ToPointer("always_false_cache"), 393 Statement: fastly.ToPointer("false"), 394 Type: fastly.ToPointer("CACHE"), 395 Priority: fastly.ToPointer(10), 396 }, 397 }, nil 398 } 399 400 func listConditionsError(_ *fastly.ListConditionsInput) ([]*fastly.Condition, error) { 401 return nil, errTest 402 }