github.com/akamai/AkamaiOPEN-edgegrid-golang/v8@v8.1.0/pkg/papi/cpcode_test.go (about) 1 package papi 2 3 import ( 4 "context" 5 "errors" 6 "net/http" 7 "net/http/httptest" 8 "testing" 9 10 "github.com/akamai/AkamaiOPEN-edgegrid-golang/v8/pkg/tools" 11 "github.com/stretchr/testify/assert" 12 "github.com/stretchr/testify/require" 13 ) 14 15 func TestPapi_GetCPCodes(t *testing.T) { 16 tests := map[string]struct { 17 params GetCPCodesRequest 18 responseStatus int 19 responseBody string 20 expectedPath string 21 expectedResponse *GetCPCodesResponse 22 withError func(*testing.T, error) 23 }{ 24 "200 OK": { 25 params: GetCPCodesRequest{ 26 ContractID: "contract", 27 GroupID: "group", 28 }, 29 responseStatus: http.StatusOK, 30 responseBody: ` 31 { 32 "accountId": "acc", 33 "contractId": "contract", 34 "groupId": "group", 35 "cpcodes": { 36 "items": [ 37 { 38 "cpcodeId": "cpcode_id", 39 "cpcodeName": "cpcode_name", 40 "createdDate": "2020-09-10T15:06:13Z", 41 "productIds": [ 42 "prd_Web_App_Accel" 43 ] 44 } 45 ] 46 } 47 }`, 48 expectedPath: "/papi/v1/cpcodes?contractId=contract&groupId=group", 49 expectedResponse: &GetCPCodesResponse{ 50 AccountID: "acc", 51 ContractID: "contract", 52 GroupID: "group", 53 CPCodes: CPCodeItems{Items: []CPCode{ 54 { 55 ID: "cpcode_id", 56 Name: "cpcode_name", 57 CreatedDate: "2020-09-10T15:06:13Z", 58 ProductIDs: []string{"prd_Web_App_Accel"}, 59 }, 60 }}, 61 }, 62 }, 63 "500 internal server error": { 64 params: GetCPCodesRequest{ 65 ContractID: "contract", 66 GroupID: "group", 67 }, 68 responseStatus: http.StatusInternalServerError, 69 responseBody: ` 70 { 71 "type": "internal_error", 72 "title": "Internal Server Error", 73 "detail": "Error fetching cp codes", 74 "status": 500 75 }`, 76 expectedPath: "/papi/v1/cpcodes?contractId=contract&groupId=group", 77 withError: func(t *testing.T, err error) { 78 want := &Error{ 79 Type: "internal_error", 80 Title: "Internal Server Error", 81 Detail: "Error fetching cp codes", 82 StatusCode: http.StatusInternalServerError, 83 } 84 assert.True(t, errors.Is(err, want), "want: %s; got: %s", want, err) 85 }, 86 }, 87 "empty group ID": { 88 params: GetCPCodesRequest{ 89 ContractID: "contract", 90 GroupID: "", 91 }, 92 withError: func(t *testing.T, err error) { 93 want := ErrStructValidation 94 assert.True(t, errors.Is(err, want), "want: %s; got: %s", want, err) 95 assert.Contains(t, err.Error(), "GroupID") 96 }, 97 }, 98 "empty contract ID": { 99 params: GetCPCodesRequest{ 100 ContractID: "", 101 GroupID: "group", 102 }, 103 withError: func(t *testing.T, err error) { 104 want := ErrStructValidation 105 assert.True(t, errors.Is(err, want), "want: %s; got: %s", want, err) 106 assert.Contains(t, err.Error(), "ContractID") 107 }, 108 }, 109 } 110 111 for name, test := range tests { 112 t.Run(name, func(t *testing.T) { 113 mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 114 assert.Equal(t, test.expectedPath, r.URL.String()) 115 assert.Equal(t, http.MethodGet, r.Method) 116 w.WriteHeader(test.responseStatus) 117 _, err := w.Write([]byte(test.responseBody)) 118 assert.NoError(t, err) 119 })) 120 client := mockAPIClient(t, mockServer) 121 result, err := client.GetCPCodes(context.Background(), test.params) 122 if test.withError != nil { 123 test.withError(t, err) 124 return 125 } 126 require.NoError(t, err) 127 assert.Equal(t, test.expectedResponse, result) 128 }) 129 } 130 } 131 132 func TestPapi_GetCPCode(t *testing.T) { 133 tests := map[string]struct { 134 params GetCPCodeRequest 135 responseStatus int 136 responseBody string 137 expectedPath string 138 expectedResponse *GetCPCodesResponse 139 withError func(*testing.T, error) 140 }{ 141 "200 OK": { 142 params: GetCPCodeRequest{ 143 ContractID: "contract", 144 GroupID: "group", 145 CPCodeID: "cpcodeID", 146 }, 147 responseStatus: http.StatusOK, 148 responseBody: ` 149 { 150 "accountId": "acc", 151 "contractId": "contract", 152 "groupId": "group", 153 "cpcodes": { 154 "items": [ 155 { 156 "cpcodeId": "cpcodeID", 157 "cpcodeName": "cpcode_name", 158 "createdDate": "2020-09-10T15:06:13Z", 159 "productIds": [ 160 "prd_Web_App_Accel" 161 ] 162 } 163 ] 164 } 165 }`, 166 expectedPath: "/papi/v1/cpcodes/cpcodeID?contractId=contract&groupId=group", 167 expectedResponse: &GetCPCodesResponse{ 168 AccountID: "acc", 169 ContractID: "contract", 170 GroupID: "group", 171 CPCodes: CPCodeItems{Items: []CPCode{ 172 { 173 ID: "cpcodeID", 174 Name: "cpcode_name", 175 CreatedDate: "2020-09-10T15:06:13Z", 176 ProductIDs: []string{"prd_Web_App_Accel"}, 177 }, 178 }}, 179 CPCode: CPCode{ 180 ID: "cpcodeID", 181 Name: "cpcode_name", 182 CreatedDate: "2020-09-10T15:06:13Z", 183 ProductIDs: []string{"prd_Web_App_Accel"}, 184 }, 185 }, 186 }, 187 "CP Code not found": { 188 params: GetCPCodeRequest{ 189 ContractID: "contract", 190 GroupID: "group", 191 CPCodeID: "cpcodeID", 192 }, 193 responseStatus: http.StatusOK, 194 responseBody: ` 195 { 196 "accountId": "acc", 197 "contractId": "contract", 198 "groupId": "group", 199 "cpcodes": { 200 "items": [ 201 ] 202 } 203 }`, 204 expectedPath: "/papi/v1/cpcodes/cpcodeID?contractId=contract&groupId=group", 205 withError: func(t *testing.T, err error) { 206 assert.True(t, errors.Is(err, ErrNotFound), "want: %v; got: %v", ErrNotFound, err) 207 }, 208 }, 209 "500 internal server error": { 210 params: GetCPCodeRequest{ 211 ContractID: "contract", 212 GroupID: "group", 213 CPCodeID: "cpcodeID", 214 }, 215 responseStatus: http.StatusInternalServerError, 216 responseBody: ` 217 { 218 "type": "internal_error", 219 "title": "Internal Server Error", 220 "detail": "Error fetching cp codes", 221 "status": 500 222 }`, 223 expectedPath: "/papi/v1/cpcodes/cpcodeID?contractId=contract&groupId=group", 224 withError: func(t *testing.T, err error) { 225 want := &Error{ 226 Type: "internal_error", 227 Title: "Internal Server Error", 228 Detail: "Error fetching cp codes", 229 StatusCode: http.StatusInternalServerError, 230 } 231 assert.True(t, errors.Is(err, want), "want: %s; got: %s", want, err) 232 }, 233 }, 234 "empty cpcode ID": { 235 params: GetCPCodeRequest{ 236 ContractID: "contract", 237 GroupID: "group", 238 CPCodeID: "", 239 }, 240 withError: func(t *testing.T, err error) { 241 want := ErrStructValidation 242 assert.True(t, errors.Is(err, want), "want: %s; got: %s", want, err) 243 assert.Contains(t, err.Error(), "CPCodeID") 244 }, 245 }, 246 "empty group ID": { 247 params: GetCPCodeRequest{ 248 ContractID: "contract", 249 GroupID: "", 250 CPCodeID: "cpcodeID", 251 }, 252 withError: func(t *testing.T, err error) { 253 want := ErrStructValidation 254 assert.True(t, errors.Is(err, want), "want: %s; got: %s", want, err) 255 assert.Contains(t, err.Error(), "GroupID") 256 }, 257 }, 258 "empty contract ID": { 259 params: GetCPCodeRequest{ 260 ContractID: "", 261 GroupID: "group", 262 CPCodeID: "cpcodeID", 263 }, 264 withError: func(t *testing.T, err error) { 265 want := ErrStructValidation 266 assert.True(t, errors.Is(err, want), "want: %s; got: %s", want, err) 267 assert.Contains(t, err.Error(), "ContractID") 268 }, 269 }, 270 } 271 272 for name, test := range tests { 273 t.Run(name, func(t *testing.T) { 274 mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 275 assert.Equal(t, test.expectedPath, r.URL.String()) 276 assert.Equal(t, http.MethodGet, r.Method) 277 w.WriteHeader(test.responseStatus) 278 _, err := w.Write([]byte(test.responseBody)) 279 assert.NoError(t, err) 280 })) 281 client := mockAPIClient(t, mockServer) 282 result, err := client.GetCPCode(context.Background(), test.params) 283 if test.withError != nil { 284 test.withError(t, err) 285 return 286 } 287 require.NoError(t, err) 288 assert.Equal(t, test.expectedResponse, result) 289 }) 290 } 291 } 292 293 func TestGetCPCodeDetail(t *testing.T) { 294 tests := map[string]struct { 295 id int 296 responseStatus int 297 responseBody string 298 expectedPath string 299 expectedResponse *CPCodeDetailResponse 300 withError func(*testing.T, error) 301 }{ 302 "200 OK": { 303 id: 123, 304 responseStatus: http.StatusOK, 305 responseBody: ` 306 { 307 "cpcodeId": 123, 308 "cpcodeName": "test-cp-code", 309 "purgeable": true, 310 "accountId": "test-account-id", 311 "defaultTimezone": "GMT 0 (Greenwich Mean Time)", 312 "overrideTimezone": { 313 "timezoneId": "0", 314 "timezoneValue": "GMT 0 (Greenwich Mean Time)" 315 }, 316 "type": "Regular", 317 "contracts": [ 318 { 319 "contractId": "test-contract-id", 320 "status": "ongoing" 321 } 322 ], 323 "products": [ 324 { 325 "productId": "test-product-id", 326 "productName": "test-product-name" 327 } 328 ], 329 "accessGroup": { 330 "groupId": null, 331 "contractId": "test-contract-id" 332 } 333 }`, 334 expectedPath: "/cprg/v1/cpcodes/123", 335 expectedResponse: &CPCodeDetailResponse{ 336 ID: 123, 337 Name: "test-cp-code", 338 Purgeable: true, 339 AccountID: "test-account-id", 340 DefaultTimeZone: "GMT 0 (Greenwich Mean Time)", 341 OverrideTimeZone: CPCodeTimeZone{ 342 TimeZoneID: "0", 343 TimeZoneValue: "GMT 0 (Greenwich Mean Time)", 344 }, 345 Type: "Regular", 346 Contracts: []CPCodeContract{ 347 { 348 ContractID: "test-contract-id", 349 Status: "ongoing", 350 }, 351 }, 352 Products: []CPCodeProduct{ 353 { 354 ProductID: "test-product-id", 355 ProductName: "test-product-name", 356 }, 357 }, 358 }, 359 }, 360 "500 internal server error": { 361 id: 123, 362 responseStatus: http.StatusInternalServerError, 363 responseBody: ` 364 { 365 "type": "internal_error", 366 "title": "Server Error", 367 "detail": "Error fetching cp codes", 368 "status": 500 369 }`, 370 expectedPath: "/cprg/v1/cpcodes/123", 371 withError: func(t *testing.T, err error) { 372 want := &Error{ 373 Type: "internal_error", 374 Title: "Server Error", 375 Detail: "Error fetching cp codes", 376 StatusCode: http.StatusInternalServerError, 377 } 378 assert.True(t, errors.Is(err, want), "want: %s; got: %s", want, err) 379 }, 380 }, 381 } 382 383 for name, test := range tests { 384 t.Run(name, func(t *testing.T) { 385 mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 386 assert.Equal(t, test.expectedPath, r.URL.String()) 387 assert.Equal(t, http.MethodGet, r.Method) 388 w.WriteHeader(test.responseStatus) 389 _, err := w.Write([]byte(test.responseBody)) 390 assert.NoError(t, err) 391 })) 392 client := mockAPIClient(t, mockServer) 393 result, err := client.GetCPCodeDetail(context.Background(), test.id) 394 if test.withError != nil { 395 test.withError(t, err) 396 return 397 } 398 require.NoError(t, err) 399 assert.Equal(t, test.expectedResponse, result) 400 }) 401 } 402 } 403 404 func TestPapi_CreateCPCode(t *testing.T) { 405 tests := map[string]struct { 406 params CreateCPCodeRequest 407 responseStatus int 408 responseBody string 409 expectedPath string 410 expected *CreateCPCodeResponse 411 withError func(*testing.T, error) 412 }{ 413 "201 Created": { 414 params: CreateCPCodeRequest{ 415 ContractID: "contract", 416 GroupID: "group", 417 CPCode: CreateCPCode{ 418 ProductID: "productID", 419 CPCodeName: "cpcodeName", 420 }, 421 }, 422 responseStatus: http.StatusCreated, 423 responseBody: ` 424 { 425 "cpcodeLink": "/papi/v1/cpcodes/123?contractId=contract-1TJZFW&groupId=group" 426 }`, 427 expectedPath: "/papi/v1/cpcodes?contractId=contract&groupId=group", 428 expected: &CreateCPCodeResponse{ 429 CPCodeLink: "/papi/v1/cpcodes/123?contractId=contract-1TJZFW&groupId=group", 430 CPCodeID: "123", 431 }, 432 }, 433 "500 Internal Server Error": { 434 params: CreateCPCodeRequest{ 435 ContractID: "contract", 436 GroupID: "group", 437 CPCode: CreateCPCode{ 438 ProductID: "productID", 439 CPCodeName: "cpcodeName", 440 }, 441 }, 442 responseStatus: http.StatusInternalServerError, 443 responseBody: ` 444 { 445 "type": "internal_error", 446 "title": "Internal Server Error", 447 "detail": "Error fetching cp codes", 448 "status": 500 449 }`, 450 expectedPath: "/papi/v1/cpcodes?contractId=contract&groupId=group", 451 withError: func(t *testing.T, err error) { 452 want := &Error{ 453 Type: "internal_error", 454 Title: "Internal Server Error", 455 Detail: "Error fetching cp codes", 456 StatusCode: http.StatusInternalServerError, 457 } 458 assert.True(t, errors.Is(err, want), "want: %s; got: %s", want, err) 459 }, 460 }, 461 "empty group ID": { 462 params: CreateCPCodeRequest{ 463 ContractID: "contract", 464 GroupID: "", 465 CPCode: CreateCPCode{ 466 ProductID: "productID", 467 CPCodeName: "cpCodeName", 468 }, 469 }, 470 withError: func(t *testing.T, err error) { 471 want := ErrStructValidation 472 assert.True(t, errors.Is(err, want), "want: %s; got: %s", want, err) 473 assert.Contains(t, err.Error(), "GroupID") 474 }, 475 }, 476 "empty contract ID": { 477 params: CreateCPCodeRequest{ 478 ContractID: "", 479 GroupID: "group", 480 CPCode: CreateCPCode{ 481 ProductID: "productID", 482 CPCodeName: "cpCodeName", 483 }, 484 }, 485 withError: func(t *testing.T, err error) { 486 want := ErrStructValidation 487 assert.True(t, errors.Is(err, want), "want: %s; got: %s", want, err) 488 assert.Contains(t, err.Error(), "ContractID") 489 }, 490 }, 491 "empty product ID": { 492 params: CreateCPCodeRequest{ 493 ContractID: "contractID", 494 GroupID: "group", 495 CPCode: CreateCPCode{ 496 ProductID: "", 497 CPCodeName: "cpCodeName", 498 }, 499 }, 500 withError: func(t *testing.T, err error) { 501 want := ErrStructValidation 502 assert.True(t, errors.Is(err, want), "want: %s; got: %s", want, err) 503 assert.Contains(t, err.Error(), "ProductID") 504 }, 505 }, 506 "empty cp code name": { 507 params: CreateCPCodeRequest{ 508 ContractID: "", 509 GroupID: "group", 510 CPCode: CreateCPCode{ 511 ProductID: "productID", 512 CPCodeName: "", 513 }, 514 }, 515 withError: func(t *testing.T, err error) { 516 want := ErrStructValidation 517 assert.True(t, errors.Is(err, want), "want: %s; got: %s", want, err) 518 assert.Contains(t, err.Error(), "CPCodeName") 519 }, 520 }, 521 "invalid response location": { 522 params: CreateCPCodeRequest{ 523 ContractID: "contract", 524 GroupID: "group", 525 CPCode: CreateCPCode{ 526 ProductID: "productID", 527 CPCodeName: "cpcodeName", 528 }, 529 }, 530 responseStatus: http.StatusCreated, 531 responseBody: ` 532 { 533 "cpcodeLink": ":" 534 }`, 535 expectedPath: "/papi/v1/cpcodes?contractId=contract&groupId=group", 536 withError: func(t *testing.T, err error) { 537 want := ErrInvalidResponseLink 538 assert.True(t, errors.Is(err, want), "want: %s; got: %s", want, err) 539 }, 540 }, 541 } 542 543 for name, test := range tests { 544 t.Run(name, func(t *testing.T) { 545 mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 546 assert.Equal(t, test.expectedPath, r.URL.String()) 547 assert.Equal(t, http.MethodPost, r.Method) 548 w.WriteHeader(test.responseStatus) 549 _, err := w.Write([]byte(test.responseBody)) 550 assert.NoError(t, err) 551 })) 552 client := mockAPIClient(t, mockServer) 553 result, err := client.CreateCPCode(context.Background(), test.params) 554 if test.withError != nil { 555 test.withError(t, err) 556 return 557 } 558 require.NoError(t, err) 559 assert.Equal(t, test.expected, result) 560 }) 561 } 562 } 563 564 func TestUpdateCPCode(t *testing.T) { 565 tests := map[string]struct { 566 params UpdateCPCodeRequest 567 responseStatus int 568 responseBody string 569 expectedPath string 570 expectedResponse *CPCodeDetailResponse 571 withError func(*testing.T, error) 572 }{ 573 "200 OK Update name": { 574 params: UpdateCPCodeRequest{ 575 ID: 123, 576 Name: "test-cp-code-updated", 577 Contracts: []CPCodeContract{ 578 { 579 ContractID: "test-contract-id", 580 Status: "ongoing", 581 }, 582 }, 583 Products: []CPCodeProduct{ 584 { 585 ProductID: "test-product-id", 586 ProductName: "test-product-name", 587 }, 588 }, 589 }, 590 responseStatus: http.StatusOK, 591 responseBody: ` 592 { 593 "cpcodeId": 123, 594 "cpcodeName": "test-cp-code-updated", 595 "purgeable": true, 596 "accountId": "test-account-id", 597 "defaultTimezone": "GMT 0 (Greenwich Mean Time)", 598 "overrideTimezone": { 599 "timezoneId": "0", 600 "timezoneValue": "GMT 0 (Greenwich Mean Time)" 601 }, 602 "type": "Regular", 603 "contracts": [ 604 { 605 "contractId": "test-contract-id", 606 "status": "ongoing" 607 } 608 ], 609 "products": [ 610 { 611 "productId": "test-product-id", 612 "productName": "test-product-name" 613 } 614 ], 615 "accessGroup": { 616 "groupId": null, 617 "contractId": "test-contract-id" 618 } 619 }`, 620 expectedPath: "/cprg/v1/cpcodes/123", 621 expectedResponse: &CPCodeDetailResponse{ 622 ID: 123, 623 Name: "test-cp-code-updated", 624 Purgeable: true, 625 AccountID: "test-account-id", 626 DefaultTimeZone: "GMT 0 (Greenwich Mean Time)", 627 OverrideTimeZone: CPCodeTimeZone{ 628 TimeZoneID: "0", 629 TimeZoneValue: "GMT 0 (Greenwich Mean Time)", 630 }, 631 Type: "Regular", 632 Contracts: []CPCodeContract{ 633 { 634 ContractID: "test-contract-id", 635 Status: "ongoing", 636 }, 637 }, 638 Products: []CPCodeProduct{ 639 { 640 ProductID: "test-product-id", 641 ProductName: "test-product-name", 642 }, 643 }, 644 }, 645 }, 646 "200 OK Update time zone": { 647 params: UpdateCPCodeRequest{ 648 ID: 123, 649 Name: "test-cp-code", 650 OverrideTimeZone: &CPCodeTimeZone{ 651 TimeZoneID: "1", 652 TimeZoneValue: "GMT + 1", 653 }, 654 Contracts: []CPCodeContract{ 655 { 656 ContractID: "test-contract-id", 657 Status: "ongoing", 658 }, 659 }, 660 Products: []CPCodeProduct{ 661 { 662 ProductID: "test-product-id", 663 ProductName: "test-product-name", 664 }, 665 }, 666 }, 667 responseStatus: http.StatusOK, 668 responseBody: ` 669 { 670 "cpcodeId": 123, 671 "cpcodeName": "test-cp-code-updated", 672 "purgeable": true, 673 "accountId": "test-account-id", 674 "defaultTimezone": "GMT 0 (Greenwich Mean Time)", 675 "overrideTimezone": { 676 "timezoneId": "1", 677 "timezoneValue": "GMT + 1" 678 }, 679 "type": "Regular", 680 "contracts": [ 681 { 682 "contractId": "test-contract-id", 683 "status": "ongoing" 684 } 685 ], 686 "products": [ 687 { 688 "productId": "test-product-id", 689 "productName": "test-product-name" 690 } 691 ], 692 "accessGroup": { 693 "groupId": null, 694 "contractId": "test-contract-id" 695 } 696 }`, 697 expectedPath: "/cprg/v1/cpcodes/123", 698 expectedResponse: &CPCodeDetailResponse{ 699 ID: 123, 700 Name: "test-cp-code-updated", 701 Purgeable: true, 702 AccountID: "test-account-id", 703 DefaultTimeZone: "GMT 0 (Greenwich Mean Time)", 704 OverrideTimeZone: CPCodeTimeZone{ 705 TimeZoneID: "1", 706 TimeZoneValue: "GMT + 1", 707 }, 708 Type: "Regular", 709 Contracts: []CPCodeContract{ 710 { 711 ContractID: "test-contract-id", 712 Status: "ongoing", 713 }, 714 }, 715 Products: []CPCodeProduct{ 716 { 717 ProductID: "test-product-id", 718 ProductName: "test-product-name", 719 }, 720 }, 721 }, 722 }, 723 "200 OK Update purgeable": { 724 params: UpdateCPCodeRequest{ 725 ID: 123, 726 Name: "test-cp-code", 727 Purgeable: tools.BoolPtr(false), 728 Contracts: []CPCodeContract{ 729 { 730 ContractID: "test-contract-id", 731 Status: "ongoing", 732 }, 733 }, 734 Products: []CPCodeProduct{ 735 { 736 ProductID: "test-product-id", 737 ProductName: "test-product-name", 738 }, 739 }, 740 }, 741 responseStatus: http.StatusOK, 742 responseBody: ` 743 { 744 "cpcodeId": 123, 745 "cpcodeName": "test-cp-code-updated", 746 "purgeable": false, 747 "accountId": "test-account-id", 748 "defaultTimezone": "GMT 0 (Greenwich Mean Time)", 749 "overrideTimezone": { 750 "timezoneId": "0", 751 "timezoneValue": "GMT 0 (Greenwich Mean Time)" 752 }, 753 "type": "Regular", 754 "contracts": [ 755 { 756 "contractId": "test-contract-id", 757 "status": "ongoing" 758 } 759 ], 760 "products": [ 761 { 762 "productId": "test-product-id", 763 "productName": "test-product-name" 764 } 765 ], 766 "accessGroup": { 767 "groupId": null, 768 "contractId": "test-contract-id" 769 } 770 }`, 771 expectedPath: "/cprg/v1/cpcodes/123", 772 expectedResponse: &CPCodeDetailResponse{ 773 ID: 123, 774 Name: "test-cp-code-updated", 775 Purgeable: false, 776 AccountID: "test-account-id", 777 DefaultTimeZone: "GMT 0 (Greenwich Mean Time)", 778 OverrideTimeZone: CPCodeTimeZone{ 779 TimeZoneID: "0", 780 TimeZoneValue: "GMT 0 (Greenwich Mean Time)", 781 }, 782 Type: "Regular", 783 Contracts: []CPCodeContract{ 784 { 785 ContractID: "test-contract-id", 786 Status: "ongoing", 787 }, 788 }, 789 Products: []CPCodeProduct{ 790 { 791 ProductID: "test-product-id", 792 ProductName: "test-product-name", 793 }, 794 }, 795 }, 796 }, 797 "500 internal server error": { 798 params: UpdateCPCodeRequest{ 799 ID: 123, 800 Name: "test-cp-code-updated", 801 Contracts: []CPCodeContract{ 802 { 803 ContractID: "test-contract-id", 804 Status: "ongoing", 805 }, 806 }, 807 Products: []CPCodeProduct{ 808 { 809 ProductID: "test-product-id", 810 ProductName: "test-product-name", 811 }, 812 }, 813 }, 814 responseStatus: http.StatusInternalServerError, 815 responseBody: ` 816 { 817 "type": "internal_error", 818 "title": "Server Error", 819 "detail": "Error updating cp code", 820 "status": 500 821 }`, 822 expectedPath: "/cprg/v1/cpcodes/123", 823 withError: func(t *testing.T, err error) { 824 want := &Error{ 825 Type: "internal_error", 826 Title: "Server Error", 827 Detail: "Error updating cp code", 828 StatusCode: http.StatusInternalServerError, 829 } 830 assert.True(t, errors.Is(err, want), "want: %s; got: %s", want, err) 831 }, 832 }, 833 "validation - id is required": { 834 params: UpdateCPCodeRequest{ 835 Name: "test-cp-code-updated", 836 Contracts: []CPCodeContract{ 837 { 838 ContractID: "test-contract-id", 839 Status: "ongoing", 840 }, 841 }, 842 Products: []CPCodeProduct{ 843 { 844 ProductID: "test-product-id", 845 ProductName: "test-product-name", 846 }, 847 }, 848 }, 849 expectedPath: "/cprg/v1/cpcodes/123", 850 withError: func(t *testing.T, err error) { 851 want := ErrStructValidation 852 assert.True(t, errors.Is(err, want), "want: %s; got: %s", want, err) 853 }, 854 }, 855 "validation - name is required": { 856 params: UpdateCPCodeRequest{ 857 ID: 123, 858 Contracts: []CPCodeContract{ 859 { 860 ContractID: "test-contract-id", 861 Status: "ongoing", 862 }, 863 }, 864 Products: []CPCodeProduct{ 865 { 866 ProductID: "test-product-id", 867 ProductName: "test-product-name", 868 }, 869 }, 870 }, 871 expectedPath: "/cprg/v1/cpcodes/123", 872 withError: func(t *testing.T, err error) { 873 want := ErrStructValidation 874 assert.True(t, errors.Is(err, want), "want: %s; got: %s", want, err) 875 }, 876 }, 877 "validation - contracts is required": { 878 params: UpdateCPCodeRequest{ 879 ID: 123, 880 Name: "test-cp-code-updated", 881 Products: []CPCodeProduct{ 882 { 883 ProductID: "test-product-id", 884 ProductName: "test-product-name", 885 }, 886 }, 887 }, 888 expectedPath: "/cprg/v1/cpcodes/123", 889 withError: func(t *testing.T, err error) { 890 want := ErrStructValidation 891 assert.True(t, errors.Is(err, want), "want: %s; got: %s", want, err) 892 }, 893 }, 894 "validation - contract id is required": { 895 params: UpdateCPCodeRequest{ 896 ID: 123, 897 Name: "test-cp-code-updated", 898 Contracts: []CPCodeContract{ 899 { 900 Status: "ongoing", 901 }, 902 }, 903 Products: []CPCodeProduct{ 904 { 905 ProductID: "test-product-id", 906 ProductName: "test-product-name", 907 }, 908 }, 909 }, 910 expectedPath: "/cprg/v1/cpcodes/123", 911 withError: func(t *testing.T, err error) { 912 want := ErrStructValidation 913 assert.True(t, errors.Is(err, want), "want: %s; got: %s", want, err) 914 }, 915 }, 916 "validation - products is required": { 917 params: UpdateCPCodeRequest{ 918 ID: 123, 919 Name: "test-cp-code-updated", 920 Contracts: []CPCodeContract{ 921 { 922 ContractID: "test-contract-id", 923 Status: "ongoing", 924 }, 925 }, 926 }, 927 expectedPath: "/cprg/v1/cpcodes/123", 928 withError: func(t *testing.T, err error) { 929 want := ErrStructValidation 930 assert.True(t, errors.Is(err, want), "want: %s; got: %s", want, err) 931 }, 932 }, 933 "validation - product id is required": { 934 params: UpdateCPCodeRequest{ 935 ID: 123, 936 Name: "test-cp-code-updated", 937 Contracts: []CPCodeContract{ 938 { 939 ContractID: "test-contract-id", 940 Status: "ongoing", 941 }, 942 }, 943 Products: []CPCodeProduct{ 944 { 945 ProductName: "test-product-name", 946 }, 947 }, 948 }, 949 expectedPath: "/cprg/v1/cpcodes/123", 950 withError: func(t *testing.T, err error) { 951 want := ErrStructValidation 952 assert.True(t, errors.Is(err, want), "want: %s; got: %s", want, err) 953 }, 954 }, 955 "validation - time zone id is required": { 956 params: UpdateCPCodeRequest{ 957 ID: 123, 958 Name: "test-cp-code-updated", 959 OverrideTimeZone: &CPCodeTimeZone{ 960 TimeZoneValue: "GMT + 1", 961 }, 962 Contracts: []CPCodeContract{ 963 { 964 ContractID: "test-contract-id", 965 Status: "ongoing", 966 }, 967 }, 968 Products: []CPCodeProduct{ 969 { 970 ProductID: "test-product-id", 971 ProductName: "test-product-name", 972 }, 973 }, 974 }, 975 expectedPath: "/cprg/v1/cpcodes/123", 976 withError: func(t *testing.T, err error) { 977 want := ErrStructValidation 978 assert.True(t, errors.Is(err, want), "want: %s; got: %s", want, err) 979 }, 980 }, 981 } 982 983 for name, test := range tests { 984 t.Run(name, func(t *testing.T) { 985 mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 986 assert.Equal(t, test.expectedPath, r.URL.String()) 987 assert.Equal(t, http.MethodPut, r.Method) 988 w.WriteHeader(test.responseStatus) 989 _, err := w.Write([]byte(test.responseBody)) 990 assert.NoError(t, err) 991 })) 992 client := mockAPIClient(t, mockServer) 993 result, err := client.UpdateCPCode(context.Background(), test.params) 994 if test.withError != nil { 995 test.withError(t, err) 996 return 997 } 998 require.NoError(t, err) 999 assert.Equal(t, test.expectedResponse, result) 1000 }) 1001 } 1002 }