github.com/akamai/AkamaiOPEN-edgegrid-golang/v8@v8.1.0/pkg/papi/include_activations_test.go (about) 1 package papi 2 3 import ( 4 "context" 5 "errors" 6 "io/ioutil" 7 "net/http" 8 "net/http/httptest" 9 "testing" 10 11 "github.com/stretchr/testify/assert" 12 "github.com/stretchr/testify/require" 13 ) 14 15 func TestActivateInclude(t *testing.T) { 16 tests := map[string]struct { 17 params ActivateIncludeRequest 18 expectedRequestBody string 19 responseStatus int 20 responseBody string 21 expectedPath string 22 expectedResponse *ActivationIncludeResponse 23 withError error 24 assertError func(*testing.T, error) 25 }{ 26 "201 Activate include acknowledging all the warnings": { 27 params: ActivateIncludeRequest{ 28 IncludeID: "inc_12345", 29 Version: 4, 30 Network: ActivationNetworkStaging, 31 Note: "test activation", 32 NotifyEmails: []string{"jbond@example.com"}, 33 AcknowledgeAllWarnings: true, 34 }, 35 expectedRequestBody: `{"acknowledgeAllWarnings":true,"activationType":"ACTIVATE","ignoreHttpErrors":true,"includeVersion":4,"network":"STAGING","note":"test activation","notifyEmails":["jbond@example.com"]}`, 36 expectedPath: "/papi/v1/includes/inc_12345/activations", 37 responseStatus: http.StatusCreated, 38 responseBody: ` 39 { 40 "activationLink": "/papi/v1/includes/inc_12345/activations/temporary-activation-id" 41 }`, 42 expectedResponse: &ActivationIncludeResponse{ 43 ActivationID: "temporary-activation-id", 44 ActivationLink: "/papi/v1/includes/inc_12345/activations/temporary-activation-id", 45 }, 46 }, 47 "201 Activate include": { 48 params: ActivateIncludeRequest{ 49 IncludeID: "inc_12345", 50 Version: 4, 51 Network: ActivationNetworkStaging, 52 Note: "test activation", 53 NotifyEmails: []string{"jbond@example.com"}, 54 }, 55 expectedRequestBody: `{"acknowledgeAllWarnings":false,"activationType":"ACTIVATE","ignoreHttpErrors":true,"includeVersion":4,"network":"STAGING","note":"test activation","notifyEmails":["jbond@example.com"]}`, 56 expectedPath: "/papi/v1/includes/inc_12345/activations", 57 responseStatus: http.StatusCreated, 58 responseBody: ` 59 { 60 "activationLink": "/papi/v1/includes/inc_12345/activations/temporary-activation-id" 61 }`, 62 expectedResponse: &ActivationIncludeResponse{ 63 ActivationID: "temporary-activation-id", 64 ActivationLink: "/papi/v1/includes/inc_12345/activations/temporary-activation-id", 65 }, 66 }, 67 "201 Activate include with ComplianceRecord None": { 68 params: ActivateIncludeRequest{ 69 IncludeID: "inc_12345", 70 Version: 4, 71 Network: ActivationNetworkProduction, 72 Note: "test activation", 73 NotifyEmails: []string{"jbond@example.com"}, 74 ComplianceRecord: &ComplianceRecordNone{ 75 CustomerEmail: "sb@akamai.com", 76 PeerReviewedBy: "sb@akamai.com", 77 UnitTested: true, 78 TicketID: "123", 79 }, 80 }, 81 expectedRequestBody: `{"acknowledgeAllWarnings":false,"activationType":"ACTIVATE","ignoreHttpErrors":true,"includeVersion":4,"network":"PRODUCTION","note":"test activation","notifyEmails":["jbond@example.com"], "complianceRecord":{"customerEmail":"sb@akamai.com", "noncomplianceReason":"NONE", "peerReviewedBy":"sb@akamai.com", "unitTested":true, "ticketId":"123"}}`, 82 expectedPath: "/papi/v1/includes/inc_12345/activations", 83 responseStatus: http.StatusCreated, 84 responseBody: ` 85 { 86 "activationLink": "/papi/v1/includes/inc_12345/activations/temporary-activation-id" 87 }`, 88 expectedResponse: &ActivationIncludeResponse{ 89 ActivationID: "temporary-activation-id", 90 ActivationLink: "/papi/v1/includes/inc_12345/activations/temporary-activation-id", 91 }, 92 }, 93 "201 Activate include with ComplianceRecord Other": { 94 params: ActivateIncludeRequest{ 95 IncludeID: "inc_12345", 96 Version: 4, 97 Network: ActivationNetworkProduction, 98 Note: "test activation", 99 NotifyEmails: []string{"jbond@example.com"}, 100 ComplianceRecord: &ComplianceRecordOther{ 101 OtherNoncomplianceReason: "some other reason", 102 TicketID: "123", 103 }, 104 }, 105 expectedRequestBody: `{"acknowledgeAllWarnings":false,"activationType":"ACTIVATE","ignoreHttpErrors":true,"includeVersion":4,"network":"PRODUCTION","note":"test activation","notifyEmails":["jbond@example.com"], "complianceRecord":{"otherNoncomplianceReason":"some other reason", "noncomplianceReason":"OTHER", "ticketId":"123"}}`, 106 expectedPath: "/papi/v1/includes/inc_12345/activations", 107 responseStatus: http.StatusCreated, 108 responseBody: ` 109 { 110 "activationLink": "/papi/v1/includes/inc_12345/activations/temporary-activation-id" 111 }`, 112 expectedResponse: &ActivationIncludeResponse{ 113 ActivationID: "temporary-activation-id", 114 ActivationLink: "/papi/v1/includes/inc_12345/activations/temporary-activation-id", 115 }, 116 }, 117 "201 Activate include with ComplianceRecord No_Production_Traffic": { 118 params: ActivateIncludeRequest{ 119 IncludeID: "inc_12345", 120 Version: 4, 121 Network: ActivationNetworkProduction, 122 Note: "test activation", 123 NotifyEmails: []string{"jbond@example.com"}, 124 ComplianceRecord: &ComplianceRecordNoProductionTraffic{ 125 TicketID: "123", 126 }, 127 }, 128 expectedRequestBody: `{"acknowledgeAllWarnings":false,"activationType":"ACTIVATE","ignoreHttpErrors":true,"includeVersion":4,"network":"PRODUCTION","note":"test activation","notifyEmails":["jbond@example.com"], "complianceRecord":{"noncomplianceReason":"NO_PRODUCTION_TRAFFIC", "ticketId":"123"}}`, 129 expectedPath: "/papi/v1/includes/inc_12345/activations", 130 responseStatus: http.StatusCreated, 131 responseBody: ` 132 { 133 "activationLink": "/papi/v1/includes/inc_12345/activations/temporary-activation-id" 134 }`, 135 expectedResponse: &ActivationIncludeResponse{ 136 ActivationID: "temporary-activation-id", 137 ActivationLink: "/papi/v1/includes/inc_12345/activations/temporary-activation-id", 138 }, 139 }, 140 "201 Activate include with ComplianceRecord Emergency": { 141 params: ActivateIncludeRequest{ 142 IncludeID: "inc_12345", 143 Version: 4, 144 Network: ActivationNetworkProduction, 145 Note: "test activation", 146 NotifyEmails: []string{"jbond@example.com"}, 147 ComplianceRecord: &ComplianceRecordEmergency{ 148 TicketID: "123", 149 }, 150 }, 151 expectedRequestBody: `{"acknowledgeAllWarnings":false,"activationType":"ACTIVATE","ignoreHttpErrors":true,"includeVersion":4,"network":"PRODUCTION","note":"test activation","notifyEmails":["jbond@example.com"], "complianceRecord":{"noncomplianceReason":"EMERGENCY", "ticketId":"123"}}`, 152 expectedPath: "/papi/v1/includes/inc_12345/activations", 153 responseStatus: http.StatusCreated, 154 responseBody: ` 155 { 156 "activationLink": "/papi/v1/includes/inc_12345/activations/temporary-activation-id" 157 }`, 158 expectedResponse: &ActivationIncludeResponse{ 159 ActivationID: "temporary-activation-id", 160 ActivationLink: "/papi/v1/includes/inc_12345/activations/temporary-activation-id", 161 }, 162 }, 163 "500 internal server error": { 164 params: ActivateIncludeRequest{ 165 IncludeID: "inc_12345", 166 Version: 4, 167 Network: ActivationNetworkStaging, 168 Note: "test activation", 169 NotifyEmails: []string{"jbond@example.com"}, 170 AcknowledgeAllWarnings: true, 171 }, 172 expectedPath: "/papi/v1/includes/inc_12345/activations", 173 responseStatus: http.StatusInternalServerError, 174 responseBody: ` 175 { 176 "type": "internal_error", 177 "title": "Internal Server Error", 178 "detail": "Error getting include", 179 "status": 500 180 }`, 181 withError: &Error{ 182 Type: "internal_error", 183 Title: "Internal Server Error", 184 Detail: "Error getting include", 185 StatusCode: http.StatusInternalServerError, 186 }, 187 }, 188 "validation error - missing include id": { 189 params: ActivateIncludeRequest{ 190 Version: 4, 191 Network: ActivationNetworkStaging, 192 NotifyEmails: []string{"jbond@example.com"}, 193 }, 194 withError: ErrStructValidation, 195 }, 196 "validation error - missing version": { 197 params: ActivateIncludeRequest{ 198 IncludeID: "inc_12345", 199 Network: ActivationNetworkStaging, 200 NotifyEmails: []string{"jbond@example.com"}, 201 }, 202 withError: ErrStructValidation, 203 }, 204 "validation error - missing network": { 205 params: ActivateIncludeRequest{ 206 IncludeID: "inc_12345", 207 Version: 4, 208 NotifyEmails: []string{"jbond@example.com"}, 209 }, 210 withError: ErrStructValidation, 211 }, 212 "validation error - missing notify emails": { 213 params: ActivateIncludeRequest{ 214 IncludeID: "inc_12345", 215 Version: 4, 216 Network: ActivationNetworkStaging, 217 }, 218 withError: ErrStructValidation, 219 }, 220 "validation error - not valid ComplianceRecordNone": { 221 params: ActivateIncludeRequest{ 222 IncludeID: "inc_12345", 223 Version: 4, 224 Network: ActivationNetworkProduction, 225 Note: "test activation", 226 NotifyEmails: []string{"jbond@example.com"}, 227 AcknowledgeAllWarnings: true, 228 ComplianceRecord: &ComplianceRecordNone{ 229 UnitTested: true, 230 TicketID: "123", 231 }, 232 }, 233 withError: ErrStructValidation, 234 assertError: func(t *testing.T, err error) { 235 assert.Contains(t, err.Error(), "CustomerEmail: cannot be blank") 236 assert.Contains(t, err.Error(), "PeerReviewedBy: cannot be blank") 237 }, 238 }, 239 "validation error - not valid UnitTested field for PRODUCTION activation network and ComplianceRecordNone": { 240 params: ActivateIncludeRequest{ 241 IncludeID: "inc_12345", 242 Version: 4, 243 Network: ActivationNetworkProduction, 244 Note: "test activation", 245 NotifyEmails: []string{"jbond@example.com"}, 246 ComplianceRecord: &ComplianceRecordNone{ 247 CustomerEmail: "sb@akamai.com", 248 PeerReviewedBy: "sb@akamai.com", 249 UnitTested: false, 250 TicketID: "123", 251 }, 252 }, 253 withError: ErrStructValidation, 254 assertError: func(t *testing.T, err error) { 255 assert.Contains(t, err.Error(), "for PRODUCTION activation network and nonComplianceRecord, UnitTested value has to be set to true, otherwise API will not work correctly") 256 }, 257 }, 258 "validation error - not valid ComplianceRecordOther": { 259 params: ActivateIncludeRequest{ 260 IncludeID: "inc_12345", 261 Version: 4, 262 Network: ActivationNetworkProduction, 263 Note: "test activation", 264 NotifyEmails: []string{"jbond@example.com"}, 265 AcknowledgeAllWarnings: true, 266 ComplianceRecord: &ComplianceRecordOther{}, 267 }, 268 withError: ErrStructValidation, 269 assertError: func(t *testing.T, err error) { 270 assert.Contains(t, err.Error(), "OtherNoncomplianceReason: cannot be blank") 271 }, 272 }, 273 } 274 for name, test := range tests { 275 t.Run(name, func(t *testing.T) { 276 mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 277 assert.Equal(t, test.expectedPath, r.URL.String()) 278 assert.Equal(t, http.MethodPost, r.Method) 279 w.WriteHeader(test.responseStatus) 280 _, err := w.Write([]byte(test.responseBody)) 281 assert.NoError(t, err) 282 283 if len(test.expectedRequestBody) > 0 { 284 body, err := ioutil.ReadAll(r.Body) 285 require.NoError(t, err) 286 assert.JSONEq(t, test.expectedRequestBody, string(body)) 287 } 288 })) 289 client := mockAPIClient(t, mockServer) 290 result, err := client.ActivateInclude(context.Background(), test.params) 291 292 if test.withError != nil || test.assertError != nil { 293 if test.withError != nil { 294 assert.True(t, errors.Is(err, test.withError), "want: %s; got: %s", test.withError, err) 295 } 296 if test.assertError != nil { 297 test.assertError(t, err) 298 } 299 return 300 } 301 302 require.NoError(t, err) 303 assert.Equal(t, test.expectedResponse, result) 304 }) 305 } 306 } 307 308 func TestDeactivateInclude(t *testing.T) { 309 tests := map[string]struct { 310 params DeactivateIncludeRequest 311 expectedRequestBody string 312 responseStatus int 313 responseBody string 314 expectedPath string 315 expectedResponse *DeactivationIncludeResponse 316 withError error 317 }{ 318 "201 Activate include acknowledging all the warnings": { 319 params: DeactivateIncludeRequest{ 320 IncludeID: "inc_12345", 321 Version: 4, 322 Network: ActivationNetworkStaging, 323 Note: "test activation", 324 NotifyEmails: []string{"jbond@example.com"}, 325 AcknowledgeAllWarnings: true, 326 }, 327 expectedRequestBody: `{"acknowledgeAllWarnings":true,"activationType":"DEACTIVATE","ignoreHttpErrors":true,"includeVersion":4,"network":"STAGING","note":"test activation","notifyEmails":["jbond@example.com"]}`, 328 expectedPath: "/papi/v1/includes/inc_12345/activations", 329 responseStatus: http.StatusCreated, 330 responseBody: ` 331 { 332 "activationLink": "/papi/v1/includes/inc_12345/activations/temporary-activation-id" 333 }`, 334 expectedResponse: &DeactivationIncludeResponse{ 335 ActivationID: "temporary-activation-id", 336 ActivationLink: "/papi/v1/includes/inc_12345/activations/temporary-activation-id", 337 }, 338 }, 339 "201 Activate include": { 340 params: DeactivateIncludeRequest{ 341 IncludeID: "inc_12345", 342 Version: 4, 343 Network: ActivationNetworkStaging, 344 Note: "test activation", 345 NotifyEmails: []string{"jbond@example.com"}, 346 }, 347 expectedRequestBody: `{"acknowledgeAllWarnings":false,"activationType":"DEACTIVATE","ignoreHttpErrors":true,"includeVersion":4,"network":"STAGING","note":"test activation","notifyEmails":["jbond@example.com"]}`, 348 expectedPath: "/papi/v1/includes/inc_12345/activations", 349 responseStatus: http.StatusCreated, 350 responseBody: ` 351 { 352 "activationLink": "/papi/v1/includes/inc_12345/activations/temporary-activation-id" 353 }`, 354 expectedResponse: &DeactivationIncludeResponse{ 355 ActivationID: "temporary-activation-id", 356 ActivationLink: "/papi/v1/includes/inc_12345/activations/temporary-activation-id", 357 }, 358 }, 359 "422 Unprocessable entity - deactivate version which is not active on some network": { 360 params: DeactivateIncludeRequest{ 361 IncludeID: "inc_12345", 362 Version: 4, 363 Network: ActivationNetworkProduction, 364 Note: "test activation", 365 NotifyEmails: []string{"jbond@example.com"}, 366 AcknowledgeAllWarnings: true, 367 }, 368 expectedPath: "/papi/v1/includes/inc_12345/activations", 369 responseStatus: http.StatusUnprocessableEntity, 370 responseBody: ` 371 { 372 "type": "https://problems.luna.akamaiapis.net/papi/v0/deactivation/include-not-active-in-production", 373 "title": "Include not active in PRODUCTION", 374 "detail": "The include cannot be deactivated because it is not active in PRODUCTION.", 375 "instance": "https://akaa-gcplhccxrheyl6kw-bcfnozqkbaydivqp.luna-dev.akamaiapis.net/papi/v1/includes/inc_12345/activations#12345", 376 "status": 422 377 }`, 378 withError: &Error{ 379 Type: "https://problems.luna.akamaiapis.net/papi/v0/deactivation/include-not-active-in-production", 380 Title: "Include not active in PRODUCTION", 381 Detail: "The include cannot be deactivated because it is not active in PRODUCTION.", 382 Instance: "https://akaa-gcplhccxrheyl6kw-bcfnozqkbaydivqp.luna-dev.akamaiapis.net/papi/v1/includes/inc_12345/activations#12345", 383 StatusCode: http.StatusUnprocessableEntity, 384 }, 385 }, 386 "500 internal server error": { 387 params: DeactivateIncludeRequest{ 388 IncludeID: "inc_12345", 389 Version: 4, 390 Network: ActivationNetworkStaging, 391 Note: "test activation", 392 NotifyEmails: []string{"jbond@example.com"}, 393 AcknowledgeAllWarnings: true, 394 }, 395 expectedPath: "/papi/v1/includes/inc_12345/activations", 396 responseStatus: http.StatusInternalServerError, 397 responseBody: ` 398 { 399 "type": "internal_error", 400 "title": "Internal Server Error", 401 "detail": "Error getting include", 402 "status": 500 403 }`, 404 withError: &Error{ 405 Type: "internal_error", 406 Title: "Internal Server Error", 407 Detail: "Error getting include", 408 StatusCode: http.StatusInternalServerError, 409 }, 410 }, 411 "validation error - missing include id": { 412 params: DeactivateIncludeRequest{ 413 Version: 4, 414 Network: ActivationNetworkStaging, 415 NotifyEmails: []string{"jbond@example.com"}, 416 }, 417 withError: ErrStructValidation, 418 }, 419 "validation error - missing version": { 420 params: DeactivateIncludeRequest{ 421 IncludeID: "inc_12345", 422 Network: ActivationNetworkStaging, 423 NotifyEmails: []string{"jbond@example.com"}, 424 }, 425 withError: ErrStructValidation, 426 }, 427 "validation error - missing network": { 428 params: DeactivateIncludeRequest{ 429 IncludeID: "inc_12345", 430 Version: 4, 431 NotifyEmails: []string{"jbond@example.com"}, 432 }, 433 withError: ErrStructValidation, 434 }, 435 "validation error - missing notify emails": { 436 params: DeactivateIncludeRequest{ 437 IncludeID: "inc_12345", 438 Version: 4, 439 Network: ActivationNetworkStaging, 440 }, 441 withError: ErrStructValidation, 442 }, 443 } 444 for name, test := range tests { 445 t.Run(name, func(t *testing.T) { 446 mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 447 assert.Equal(t, test.expectedPath, r.URL.String()) 448 assert.Equal(t, http.MethodPost, r.Method) 449 w.WriteHeader(test.responseStatus) 450 _, err := w.Write([]byte(test.responseBody)) 451 assert.NoError(t, err) 452 453 if len(test.expectedRequestBody) > 0 { 454 body, err := ioutil.ReadAll(r.Body) 455 require.NoError(t, err) 456 assert.JSONEq(t, test.expectedRequestBody, string(body)) 457 } 458 })) 459 client := mockAPIClient(t, mockServer) 460 result, err := client.DeactivateInclude(context.Background(), test.params) 461 if test.withError != nil { 462 assert.True(t, errors.Is(err, test.withError), "want: %s; got: %s", test.withError, err) 463 return 464 } 465 require.NoError(t, err) 466 assert.Equal(t, test.expectedResponse, result) 467 }) 468 } 469 } 470 471 func TestCancelIncludeActivation(t *testing.T) { 472 tests := map[string]struct { 473 params CancelIncludeActivationRequest 474 responseStatus int 475 responseBody string 476 expectedPath string 477 expectedResponse *CancelIncludeActivationResponse 478 withError error 479 }{ 480 "200 cancel include activation": { 481 params: CancelIncludeActivationRequest{ 482 IncludeID: "inc_12345", 483 ContractID: "test_contract", 484 GroupID: "test_group", 485 ActivationID: "test_activation_123", 486 }, 487 expectedPath: "/papi/v1/includes/inc_12345/activations/test_activation_123?contractId=test_contract&groupId=test_group", 488 responseStatus: http.StatusOK, 489 responseBody: ` 490 { 491 "accountId": "test_account", 492 "contractId": "test_contract", 493 "groupId": "test_group", 494 "activations": { 495 "items": [ 496 { 497 "network": "STAGING", 498 "activationType": "ACTIVATE", 499 "status": "PENDING_CANCELLATION", 500 "submitDate": "2022-12-01T13:18:57Z", 501 "updateDate": "2022-12-01T13:19:04Z", 502 "note": "test_note_1", 503 "notifyEmails": [ 504 "nomail@nomail.com" 505 ], 506 "fmaActivationState": "received", 507 "includeId": "inc_12345", 508 "includeName": "test_include_name", 509 "includeVersion": 1, 510 "includeActivationId": "test_activation_123" 511 } 512 ] 513 } 514 }`, 515 expectedResponse: &CancelIncludeActivationResponse{ 516 AccountID: "test_account", 517 ContractID: "test_contract", 518 GroupID: "test_group", 519 Activations: IncludeActivationsRes{ 520 Items: []IncludeActivation{ 521 { 522 Network: "STAGING", 523 ActivationType: ActivationTypeActivate, 524 Status: ActivationStatusCancelling, 525 SubmitDate: "2022-12-01T13:18:57Z", 526 UpdateDate: "2022-12-01T13:19:04Z", 527 Note: "test_note_1", 528 NotifyEmails: []string{"nomail@nomail.com"}, 529 FMAActivationState: "received", 530 IncludeID: "inc_12345", 531 IncludeName: "test_include_name", 532 IncludeVersion: 1, 533 IncludeActivationID: "test_activation_123", 534 }, 535 }, 536 }, 537 }, 538 }, 539 "500 internal server error": { 540 params: CancelIncludeActivationRequest{ 541 IncludeID: "inc_12345", 542 ContractID: "test_contract", 543 GroupID: "test_group", 544 ActivationID: "test_activation_123", 545 }, 546 expectedPath: "/papi/v1/includes/inc_12345/activations/test_activation_123?contractId=test_contract&groupId=test_group", 547 responseStatus: http.StatusInternalServerError, 548 responseBody: ` 549 { 550 "type": "internal_error", 551 "title": "Internal Server Error", 552 "detail": "Error cancelling include activation", 553 "status": 500 554 }`, 555 withError: &Error{ 556 Type: "internal_error", 557 Title: "Internal Server Error", 558 Detail: "Error cancelling include activation", 559 StatusCode: http.StatusInternalServerError, 560 }, 561 }, 562 "validation error - missing include id": { 563 params: CancelIncludeActivationRequest{ 564 ContractID: "test_contract", 565 GroupID: "test_group", 566 ActivationID: "test_activation_123", 567 }, 568 withError: ErrStructValidation, 569 }, 570 "validation error - contract id": { 571 params: CancelIncludeActivationRequest{ 572 IncludeID: "inc_12345", 573 GroupID: "test_group", 574 ActivationID: "test_activation_123", 575 }, 576 withError: ErrStructValidation, 577 }, 578 "validation error - group id": { 579 params: CancelIncludeActivationRequest{ 580 IncludeID: "inc_12345", 581 ContractID: "test_contract", 582 ActivationID: "test_activation_123", 583 }, 584 withError: ErrStructValidation, 585 }, 586 "validation error - activation id": { 587 params: CancelIncludeActivationRequest{ 588 IncludeID: "inc_12345", 589 ContractID: "test_contract", 590 GroupID: "test_group", 591 }, 592 withError: ErrStructValidation, 593 }, 594 } 595 for name, test := range tests { 596 t.Run(name, func(t *testing.T) { 597 mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 598 assert.Equal(t, test.expectedPath, r.URL.String()) 599 assert.Equal(t, http.MethodDelete, r.Method) 600 w.WriteHeader(test.responseStatus) 601 _, err := w.Write([]byte(test.responseBody)) 602 assert.NoError(t, err) 603 })) 604 client := mockAPIClient(t, mockServer) 605 result, err := client.CancelIncludeActivation(context.Background(), test.params) 606 if test.withError != nil { 607 assert.True(t, errors.Is(err, test.withError), "want: %s; got: %s", test.withError, err) 608 return 609 } 610 require.NoError(t, err) 611 assert.Equal(t, test.expectedResponse, result) 612 }) 613 } 614 } 615 616 func TestGetIncludeActivation(t *testing.T) { 617 tests := map[string]struct { 618 params GetIncludeActivationRequest 619 responseStatus int 620 responseBody string 621 expectedPath string 622 expectedResponse *GetIncludeActivationResponse 623 withError error 624 }{ 625 "200 Get include activation": { 626 params: GetIncludeActivationRequest{ 627 IncludeID: "inc_12345", 628 ActivationID: "atv_12345", 629 }, 630 expectedPath: "/papi/v1/includes/inc_12345/activations/atv_12345", 631 responseStatus: http.StatusOK, 632 responseBody: ` 633 { 634 "accountId": "test_account", 635 "contractId": "test_contract", 636 "groupId": "test_group", 637 "activations": { 638 "items": [ 639 { 640 "activationId": "atv_12345", 641 "network": "STAGING", 642 "activationType": "ACTIVATE", 643 "status": "ACTIVE", 644 "submitDate": "2022-10-27T12:27:54Z", 645 "updateDate": "2022-10-27T12:28:54Z", 646 "note": "DXE test activation", 647 "notifyEmails": [ 648 "test@example.com" 649 ], 650 "fmaActivationState": "steady", 651 "fallbackInfo": { 652 "fastFallbackAttempted": false, 653 "fallbackVersion": 3, 654 "canFastFallback": false, 655 "steadyStateTime": 1666873734, 656 "fastFallbackExpirationTime": 1666877334, 657 "fastFallbackRecoveryState": null 658 }, 659 "includeId": "inc_12345", 660 "includeName": "tfp_test1", 661 "includeType": "MICROSERVICES", 662 "includeVersion": 4 663 } 664 ] 665 } 666 }`, 667 expectedResponse: &GetIncludeActivationResponse{ 668 AccountID: "test_account", 669 ContractID: "test_contract", 670 GroupID: "test_group", 671 Activations: IncludeActivationsRes{ 672 Items: []IncludeActivation{ 673 { 674 ActivationID: "atv_12345", 675 Network: "STAGING", 676 ActivationType: ActivationTypeActivate, 677 Status: ActivationStatusActive, 678 SubmitDate: "2022-10-27T12:27:54Z", 679 UpdateDate: "2022-10-27T12:28:54Z", 680 Note: "DXE test activation", 681 NotifyEmails: []string{"test@example.com"}, 682 FMAActivationState: "steady", 683 FallbackInfo: &ActivationFallbackInfo{ 684 FastFallbackAttempted: false, 685 FallbackVersion: 3, 686 CanFastFallback: false, 687 SteadyStateTime: 1666873734, 688 FastFallbackExpirationTime: 1666877334, 689 }, 690 IncludeID: "inc_12345", 691 IncludeName: "tfp_test1", 692 IncludeType: "MICROSERVICES", 693 IncludeVersion: 4, 694 }, 695 }, 696 }, 697 Activation: IncludeActivation{ 698 ActivationID: "atv_12345", 699 Network: "STAGING", 700 ActivationType: ActivationTypeActivate, 701 Status: ActivationStatusActive, 702 SubmitDate: "2022-10-27T12:27:54Z", 703 UpdateDate: "2022-10-27T12:28:54Z", 704 Note: "DXE test activation", 705 NotifyEmails: []string{"test@example.com"}, 706 FMAActivationState: "steady", 707 FallbackInfo: &ActivationFallbackInfo{ 708 FastFallbackAttempted: false, 709 FallbackVersion: 3, 710 CanFastFallback: false, 711 SteadyStateTime: 1666873734, 712 FastFallbackExpirationTime: 1666877334, 713 }, 714 IncludeID: "inc_12345", 715 IncludeName: "tfp_test1", 716 IncludeType: "MICROSERVICES", 717 IncludeVersion: 4, 718 }, 719 }, 720 }, 721 "200 Get include activation with includeActivationId": { 722 params: GetIncludeActivationRequest{ 723 IncludeID: "inc_12345", 724 ActivationID: "5e597860-1107-461e-8dbe-4e7526e8dd02", 725 }, 726 expectedPath: "/papi/v1/includes/inc_12345/activations/5e597860-1107-461e-8dbe-4e7526e8dd02", 727 responseStatus: http.StatusOK, 728 responseBody: ` 729 { 730 "accountId": "test_account", 731 "contractId": "test_contract", 732 "groupId": "test_group", 733 "activations": { 734 "items": [ 735 { 736 "includeActivationId": "5e597860-1107-461e-8dbe-4e7526e8dd02", 737 "network": "STAGING", 738 "activationType": "ACTIVATE", 739 "status": "ACTIVE", 740 "submitDate": "2022-10-27T12:27:54Z", 741 "updateDate": "2022-10-27T12:28:54Z", 742 "note": "DXE test activation", 743 "notifyEmails": [ 744 "test@example.com" 745 ], 746 "fmaActivationState": "steady", 747 "fallbackInfo": { 748 "fastFallbackAttempted": false, 749 "fallbackVersion": 3, 750 "canFastFallback": false, 751 "steadyStateTime": 1666873734, 752 "fastFallbackExpirationTime": 1666877334, 753 "fastFallbackRecoveryState": null 754 }, 755 "includeId": "inc_12345", 756 "includeName": "tfp_test1", 757 "includeType": "MICROSERVICES", 758 "includeVersion": 4 759 } 760 ] 761 } 762 }`, 763 expectedResponse: &GetIncludeActivationResponse{ 764 AccountID: "test_account", 765 ContractID: "test_contract", 766 GroupID: "test_group", 767 Activations: IncludeActivationsRes{ 768 Items: []IncludeActivation{ 769 { 770 IncludeActivationID: "5e597860-1107-461e-8dbe-4e7526e8dd02", 771 Network: "STAGING", 772 ActivationType: ActivationTypeActivate, 773 Status: ActivationStatusActive, 774 SubmitDate: "2022-10-27T12:27:54Z", 775 UpdateDate: "2022-10-27T12:28:54Z", 776 Note: "DXE test activation", 777 NotifyEmails: []string{"test@example.com"}, 778 FMAActivationState: "steady", 779 FallbackInfo: &ActivationFallbackInfo{ 780 FastFallbackAttempted: false, 781 FallbackVersion: 3, 782 CanFastFallback: false, 783 SteadyStateTime: 1666873734, 784 FastFallbackExpirationTime: 1666877334, 785 }, 786 IncludeID: "inc_12345", 787 IncludeName: "tfp_test1", 788 IncludeType: "MICROSERVICES", 789 IncludeVersion: 4, 790 }, 791 }, 792 }, 793 Activation: IncludeActivation{ 794 IncludeActivationID: "5e597860-1107-461e-8dbe-4e7526e8dd02", 795 Network: "STAGING", 796 ActivationType: ActivationTypeActivate, 797 Status: ActivationStatusActive, 798 SubmitDate: "2022-10-27T12:27:54Z", 799 UpdateDate: "2022-10-27T12:28:54Z", 800 Note: "DXE test activation", 801 NotifyEmails: []string{"test@example.com"}, 802 FMAActivationState: "steady", 803 FallbackInfo: &ActivationFallbackInfo{ 804 FastFallbackAttempted: false, 805 FallbackVersion: 3, 806 CanFastFallback: false, 807 SteadyStateTime: 1666873734, 808 FastFallbackExpirationTime: 1666877334, 809 }, 810 IncludeID: "inc_12345", 811 IncludeName: "tfp_test1", 812 IncludeType: "MICROSERVICES", 813 IncludeVersion: 4, 814 }, 815 }, 816 }, 817 "200 but with activation validation error - ErrMissingComplianceRecord expected": { 818 params: GetIncludeActivationRequest{ 819 IncludeID: "inc_12345", 820 ActivationID: "atv_12345", 821 }, 822 expectedPath: "/papi/v1/includes/inc_12345/activations/atv_12345", 823 responseStatus: http.StatusOK, 824 responseBody: ` 825 { 826 "accountId": "test_account", 827 "contractId": "test_contract", 828 "groupId": "test_group", 829 "validations": { 830 "validationSummary": { 831 "completePercent": 100.0, 832 "hasValidationError": false, 833 "hasValidationWarning": false, 834 "hasSystemError": false, 835 "hasClientError": true, 836 "messageState": "HTTP_CLIENT_ERROR", 837 "errorMessage": "400 : \"{\"type\":\"missing_compliance_record\",\"title\":\"Property Manager Exception\",\"instance\":\"TestInstance\",\"status\":400,\"errors\":[{\"type\":\"missing_compliance_record\",\"title\":\"Property Manager Exception\",\"detail\":\"missing_compliance_record\"}],\"details\":{},\"messageId\":\"missing_compliance_record\",\"params\":[],\"result\":\"ERROR\"}\"" 838 }, 839 "validationErrorsItemList": { 840 "items": [] 841 }, 842 "network": "PRODUCTION" 843 }, 844 "activations": { 845 "items": [] 846 } 847 }`, 848 withError: ErrMissingComplianceRecord, 849 }, 850 "500 internal server error": { 851 params: GetIncludeActivationRequest{ 852 IncludeID: "inc_12345", 853 ActivationID: "atv_12345", 854 }, 855 expectedPath: "/papi/v1/includes/inc_12345/activations/atv_12345", 856 responseStatus: http.StatusInternalServerError, 857 responseBody: ` 858 { 859 "type": "internal_error", 860 "title": "Internal Server Error", 861 "detail": "Error getting include", 862 "status": 500 863 }`, 864 withError: &Error{ 865 Type: "internal_error", 866 Title: "Internal Server Error", 867 Detail: "Error getting include", 868 StatusCode: http.StatusInternalServerError, 869 }, 870 }, 871 "validation error - missing include id": { 872 params: GetIncludeActivationRequest{ 873 ActivationID: "atv_12345", 874 }, 875 withError: ErrStructValidation, 876 }, 877 "validation error - activation id": { 878 params: GetIncludeActivationRequest{ 879 IncludeID: "inc_12345", 880 }, 881 withError: ErrStructValidation, 882 }, 883 } 884 for name, test := range tests { 885 t.Run(name, func(t *testing.T) { 886 mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 887 assert.Equal(t, test.expectedPath, r.URL.String()) 888 assert.Equal(t, http.MethodGet, r.Method) 889 w.WriteHeader(test.responseStatus) 890 _, err := w.Write([]byte(test.responseBody)) 891 assert.NoError(t, err) 892 })) 893 client := mockAPIClient(t, mockServer) 894 result, err := client.GetIncludeActivation(context.Background(), test.params) 895 if test.withError != nil { 896 assert.True(t, errors.Is(err, test.withError), "want: %s; got: %s", test.withError, err) 897 return 898 } 899 require.NoError(t, err) 900 assert.Equal(t, test.expectedResponse, result) 901 }) 902 } 903 } 904 905 func TestListIncludeActivations(t *testing.T) { 906 tests := map[string]struct { 907 params ListIncludeActivationsRequest 908 responseStatus int 909 responseBody string 910 expectedPath string 911 expectedResponse *ListIncludeActivationsResponse 912 withError error 913 }{ 914 "200 List include activations": { 915 params: ListIncludeActivationsRequest{ 916 IncludeID: "inc_12345", 917 ContractID: "test_contract", 918 GroupID: "test_group", 919 }, 920 expectedPath: "/papi/v1/includes/inc_12345/activations?contractId=test_contract&groupId=test_group", 921 responseStatus: http.StatusOK, 922 responseBody: ` 923 { 924 "accountId": "test_account", 925 "contractId": "test_contract", 926 "groupId": "test_group", 927 "activations": { 928 "items": [ 929 { 930 "activationId": "atv_12344", 931 "network": "STAGING", 932 "activationType": "ACTIVATE", 933 "status": "ACTIVE", 934 "submitDate": "2022-10-27T12:27:54Z", 935 "updateDate": "2022-10-27T12:28:54Z", 936 "note": "test activation", 937 "notifyEmails": [ 938 "test@example.com" 939 ], 940 "fmaActivationState": "steady", 941 "fallbackInfo": { 942 "fastFallbackAttempted": false, 943 "fallbackVersion": 3, 944 "canFastFallback": false, 945 "steadyStateTime": 1666873734, 946 "fastFallbackExpirationTime": 1666877334, 947 "fastFallbackRecoveryState": null 948 }, 949 "includeId": "inc_12345", 950 "includeName": "tfp_test1", 951 "includeType": "MICROSERVICES", 952 "includeVersion": 4 953 }, 954 { 955 "activationId": "atv_12343", 956 "network": "STAGING", 957 "activationType": "ACTIVATE", 958 "status": "ACTIVE", 959 "submitDate": "2022-10-27T11:21:40Z", 960 "updateDate": "2022-10-27T11:22:54Z", 961 "note": "test activation", 962 "notifyEmails": [ 963 "test@example.com" 964 ], 965 "fmaActivationState": "steady", 966 "fallbackInfo": { 967 "fastFallbackAttempted": false, 968 "fallbackVersion": 4, 969 "canFastFallback": false, 970 "steadyStateTime": 1666869774, 971 "fastFallbackExpirationTime": 1666873374, 972 "fastFallbackRecoveryState": null 973 }, 974 "includeId": "inc_12345", 975 "includeName": "tfp_test1", 976 "includeType": "MICROSERVICES", 977 "includeVersion": 3 978 }, 979 { 980 "activationId": "atv_12343", 981 "network": "STAGING", 982 "activationType": "DEACTIVATE", 983 "status": "ACTIVE", 984 "submitDate": "2022-10-26T12:41:58Z", 985 "updateDate": "2022-10-26T13:03:04Z", 986 "note": "test activation", 987 "notifyEmails": [ 988 "test@example.com" 989 ], 990 "includeId": "inc_12345", 991 "includeName": "tfp_test1", 992 "includeType": "MICROSERVICES", 993 "includeVersion": 3 994 }, 995 { 996 "activationId": "atv_12342", 997 "network": "STAGING", 998 "activationType": "ACTIVATE", 999 "status": "ACTIVE", 1000 "submitDate": "2022-10-26T12:37:49Z", 1001 "updateDate": "2022-10-26T12:38:59Z", 1002 "note": "test activation", 1003 "notifyEmails": [ 1004 "test@example.com" 1005 ], 1006 "fmaActivationState": "steady", 1007 "fallbackInfo": { 1008 "fastFallbackAttempted": false, 1009 "fallbackVersion": 4, 1010 "canFastFallback": false, 1011 "steadyStateTime": 1666787939, 1012 "fastFallbackExpirationTime": 1666791539, 1013 "fastFallbackRecoveryState": null 1014 }, 1015 "includeId": "inc_12345", 1016 "includeName": "tfp_test1", 1017 "includeType": "MICROSERVICES", 1018 "includeVersion": 2 1019 }, 1020 { 1021 "activationId": "atv_12341", 1022 "network": "STAGING", 1023 "activationType": "ACTIVATE", 1024 "status": "ACTIVE", 1025 "submitDate": "2022-08-17T09:13:18Z", 1026 "updateDate": "2022-08-17T09:15:35Z", 1027 "note": "test activation", 1028 "notifyEmails": [ 1029 "test@example.com" 1030 ], 1031 "fmaActivationState": "steady", 1032 "fallbackInfo": { 1033 "fastFallbackAttempted": false, 1034 "fallbackVersion": 4, 1035 "canFastFallback": false, 1036 "steadyStateTime": 1660727735, 1037 "fastFallbackExpirationTime": 1660731335, 1038 "fastFallbackRecoveryState": null 1039 }, 1040 "includeId": "inc_12345", 1041 "includeName": "tfp_test1", 1042 "includeType": "MICROSERVICES", 1043 "includeVersion": 1 1044 } 1045 ] 1046 } 1047 }`, 1048 expectedResponse: &ListIncludeActivationsResponse{ 1049 AccountID: "test_account", 1050 ContractID: "test_contract", 1051 GroupID: "test_group", 1052 Activations: IncludeActivationsRes{ 1053 Items: []IncludeActivation{ 1054 { 1055 ActivationID: "atv_12344", 1056 Network: "STAGING", 1057 ActivationType: ActivationTypeActivate, 1058 Status: ActivationStatusActive, 1059 SubmitDate: "2022-10-27T12:27:54Z", 1060 UpdateDate: "2022-10-27T12:28:54Z", 1061 Note: "test activation", 1062 NotifyEmails: []string{"test@example.com"}, 1063 FMAActivationState: "steady", 1064 FallbackInfo: &ActivationFallbackInfo{ 1065 FastFallbackAttempted: false, 1066 FallbackVersion: 3, 1067 CanFastFallback: false, 1068 SteadyStateTime: 1666873734, 1069 FastFallbackExpirationTime: 1666877334, 1070 }, 1071 IncludeID: "inc_12345", 1072 IncludeName: "tfp_test1", 1073 IncludeType: "MICROSERVICES", 1074 IncludeVersion: 4, 1075 }, 1076 { 1077 ActivationID: "atv_12343", 1078 Network: "STAGING", 1079 ActivationType: ActivationTypeActivate, 1080 Status: ActivationStatusActive, 1081 SubmitDate: "2022-10-27T11:21:40Z", 1082 UpdateDate: "2022-10-27T11:22:54Z", 1083 Note: "test activation", 1084 NotifyEmails: []string{"test@example.com"}, 1085 FMAActivationState: "steady", 1086 FallbackInfo: &ActivationFallbackInfo{ 1087 FastFallbackAttempted: false, 1088 FallbackVersion: 4, 1089 CanFastFallback: false, 1090 SteadyStateTime: 1666869774, 1091 FastFallbackExpirationTime: 1666873374, 1092 }, 1093 IncludeID: "inc_12345", 1094 IncludeName: "tfp_test1", 1095 IncludeType: "MICROSERVICES", 1096 IncludeVersion: 3, 1097 }, 1098 { 1099 ActivationID: "atv_12343", 1100 Network: "STAGING", 1101 ActivationType: ActivationTypeDeactivate, 1102 Status: ActivationStatusActive, 1103 SubmitDate: "2022-10-26T12:41:58Z", 1104 UpdateDate: "2022-10-26T13:03:04Z", 1105 Note: "test activation", 1106 NotifyEmails: []string{"test@example.com"}, 1107 IncludeID: "inc_12345", 1108 IncludeName: "tfp_test1", 1109 IncludeType: "MICROSERVICES", 1110 IncludeVersion: 3, 1111 }, 1112 { 1113 ActivationID: "atv_12342", 1114 Network: "STAGING", 1115 ActivationType: ActivationTypeActivate, 1116 Status: ActivationStatusActive, 1117 SubmitDate: "2022-10-26T12:37:49Z", 1118 UpdateDate: "2022-10-26T12:38:59Z", 1119 Note: "test activation", 1120 NotifyEmails: []string{"test@example.com"}, 1121 FMAActivationState: "steady", 1122 FallbackInfo: &ActivationFallbackInfo{ 1123 FastFallbackAttempted: false, 1124 FallbackVersion: 4, 1125 CanFastFallback: false, 1126 SteadyStateTime: 1666787939, 1127 FastFallbackExpirationTime: 1666791539, 1128 }, 1129 IncludeID: "inc_12345", 1130 IncludeName: "tfp_test1", 1131 IncludeType: "MICROSERVICES", 1132 IncludeVersion: 2, 1133 }, 1134 { 1135 ActivationID: "atv_12341", 1136 Network: "STAGING", 1137 ActivationType: ActivationTypeActivate, 1138 Status: ActivationStatusActive, 1139 SubmitDate: "2022-08-17T09:13:18Z", 1140 UpdateDate: "2022-08-17T09:15:35Z", 1141 Note: "test activation", 1142 NotifyEmails: []string{"test@example.com"}, 1143 FMAActivationState: "steady", 1144 FallbackInfo: &ActivationFallbackInfo{ 1145 FastFallbackAttempted: false, 1146 FallbackVersion: 4, 1147 CanFastFallback: false, 1148 SteadyStateTime: 1660727735, 1149 FastFallbackExpirationTime: 1660731335, 1150 }, 1151 IncludeID: "inc_12345", 1152 IncludeName: "tfp_test1", 1153 IncludeType: "MICROSERVICES", 1154 IncludeVersion: 1, 1155 }, 1156 }, 1157 }, 1158 }, 1159 }, 1160 "500 internal server error": { 1161 params: ListIncludeActivationsRequest{ 1162 IncludeID: "inc_12345", 1163 ContractID: "test_contract", 1164 GroupID: "test_group", 1165 }, 1166 expectedPath: "/papi/v1/includes/inc_12345/activations?contractId=test_contract&groupId=test_group", 1167 responseStatus: http.StatusInternalServerError, 1168 responseBody: ` 1169 { 1170 "type": "internal_error", 1171 "title": "Internal Server Error", 1172 "detail": "Error getting include", 1173 "status": 500 1174 }`, 1175 withError: &Error{ 1176 Type: "internal_error", 1177 Title: "Internal Server Error", 1178 Detail: "Error getting include", 1179 StatusCode: http.StatusInternalServerError, 1180 }, 1181 }, 1182 "validation error - missing include id": { 1183 params: ListIncludeActivationsRequest{ 1184 ContractID: "test_contract", 1185 GroupID: "test_group", 1186 }, 1187 withError: ErrStructValidation, 1188 }, 1189 "validation error - contract id": { 1190 params: ListIncludeActivationsRequest{ 1191 IncludeID: "inc_12345", 1192 GroupID: "test_group", 1193 }, 1194 withError: ErrStructValidation, 1195 }, 1196 "validation error - group id": { 1197 params: ListIncludeActivationsRequest{ 1198 IncludeID: "inc_12345", 1199 ContractID: "test_contract", 1200 }, 1201 withError: ErrStructValidation, 1202 }, 1203 } 1204 for name, test := range tests { 1205 t.Run(name, func(t *testing.T) { 1206 mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 1207 assert.Equal(t, test.expectedPath, r.URL.String()) 1208 assert.Equal(t, http.MethodGet, r.Method) 1209 w.WriteHeader(test.responseStatus) 1210 _, err := w.Write([]byte(test.responseBody)) 1211 assert.NoError(t, err) 1212 })) 1213 client := mockAPIClient(t, mockServer) 1214 result, err := client.ListIncludeActivations(context.Background(), test.params) 1215 if test.withError != nil { 1216 assert.True(t, errors.Is(err, test.withError), "want: %s; got: %s", test.withError, err) 1217 return 1218 } 1219 require.NoError(t, err) 1220 assert.Equal(t, test.expectedResponse, result) 1221 }) 1222 } 1223 } 1224 1225 func TestExtractError(t *testing.T) { 1226 tests := map[string]struct { 1227 errorMessage string 1228 wantedError *ActivationError 1229 }{ 1230 "all data": { 1231 errorMessage: "111 : \"{\"type\":\"type1\",\"title\":\"title1\",\"instance\":\"instance1\",\"status\":404,\"errors\":[{\"type\":\"type2\",\"title\":\"title2\",\"detail\":\"detail1\"}],\"details\":{},\"messageId\":\"message1\",\"params\":[],\"result\":\"result1\"}\"", 1232 wantedError: &ActivationError{ 1233 Type: "type1", 1234 Title: "title1", 1235 Instance: "instance1", 1236 Status: 404, 1237 Errors: []ActivationErrorMessage{ 1238 { 1239 Type: "type2", 1240 Title: "title2", 1241 Detail: "detail1", 1242 }, 1243 }, 1244 MessageID: "message1", 1245 Result: "result1", 1246 }, 1247 }, 1248 "minimum data": { 1249 errorMessage: "111 : \"{\"type\":\"type1\",\"title\":\"title1\",\"instance\":\"instance1\",\"status\":404,\"errors\":[{\"type\":\"type2\",\"title\":\"title2\",\"detail\":\"detail1\"}],\"messageId\":\"message1\",\"result\":\"result1\"}\"", 1250 wantedError: &ActivationError{ 1251 Type: "type1", 1252 Title: "title1", 1253 Instance: "instance1", 1254 Status: 404, 1255 Errors: []ActivationErrorMessage{ 1256 { 1257 Type: "type2", 1258 Title: "title2", 1259 Detail: "detail1", 1260 }, 1261 }, 1262 MessageID: "message1", 1263 Result: "result1", 1264 }, 1265 }, 1266 } 1267 1268 for name, test := range tests { 1269 t.Run(name, func(t *testing.T) { 1270 gotErr := extractError(test.errorMessage) 1271 assert.EqualError(t, test.wantedError, gotErr.Error()) 1272 }) 1273 } 1274 }