github.com/akamai/AkamaiOPEN-edgegrid-golang/v8@v8.1.0/pkg/clientlists/client_list_test.go (about) 1 package clientlists 2 3 import ( 4 "context" 5 "errors" 6 "fmt" 7 "io/ioutil" 8 "net/http" 9 "net/http/httptest" 10 "testing" 11 12 "github.com/akamai/AkamaiOPEN-edgegrid-golang/v8/pkg/session" 13 "github.com/akamai/AkamaiOPEN-edgegrid-golang/v8/pkg/tools" 14 "github.com/stretchr/testify/require" 15 "github.com/tj/assert" 16 ) 17 18 func TestGetClientLists(t *testing.T) { 19 uri := "/client-list/v1/lists" 20 21 tests := map[string]struct { 22 params GetClientListsRequest 23 responseStatus int 24 responseBody string 25 expectedPath string 26 expectedResponse *GetClientListsResponse 27 withError error 28 }{ 29 "200 OK": { 30 params: GetClientListsRequest{}, 31 responseStatus: http.StatusOK, 32 responseBody: ` 33 { 34 "content": [ 35 { 36 "createDate": "2023-06-06T15:58:39.225+00:00", 37 "createdBy": "ccare2", 38 "deprecated": false, 39 "filePrefix": "CL", 40 "itemsCount": 1, 41 "listId": "91596_AUDITLOGSTESTLIST", 42 "listType": "CL", 43 "name": "AUDIT LOGS - TEST LIST", 44 "productionActivationStatus": "INACTIVE", 45 "readOnly": false, 46 "shared": false, 47 "stagingActivationStatus": "INACTIVE", 48 "tags": ["green"], 49 "type": "IP", 50 "updateDate": "2023-06-06T15:58:39.225+00:00", 51 "updatedBy": "ccare2", 52 "version": 1 53 }, 54 { 55 "createDate": "2022-11-10T14:42:04.857+00:00", 56 "createdBy": "ccare2", 57 "deprecated": false, 58 "filePrefix": "CL", 59 "itemsCount": 2, 60 "listId": "85988_ANTHONYGEOLISTOPEN", 61 "listType": "CL", 62 "name": "AnthonyGeoListOPEN", 63 "notes": "This is another Geo client list for Nov 11", 64 "productionActivationStatus": "INACTIVE", 65 "readOnly": false, 66 "shared": false, 67 "stagingActivationStatus": "INACTIVE", 68 "tags": [], 69 "type": "GEO", 70 "updateDate": "2023-05-11T15:30:10.224+00:00", 71 "updatedBy": "ccare2", 72 "version": 66 73 }, 74 { 75 "createDate": "2022-10-17T13:39:25.319+00:00", 76 "createdBy": "ccare2", 77 "deprecated": false, 78 "filePrefix": "CL", 79 "itemsCount": 0, 80 "listId": "85552_ANTHONYFILEHASHLIST", 81 "listType": "CL", 82 "name": "File Hash List", 83 "notes": "This is another File hash client list for Oct 17", 84 "productionActivationStatus": "PENDING_ACTIVATION", 85 "readOnly": false, 86 "shared": false, 87 "stagingActivationStatus": "INACTIVE", 88 "tags": ["blue"], 89 "type": "TLS_FINGERPRINT", 90 "updateDate": "2023-06-05T06:56:19.004+00:00", 91 "updatedBy": "ccare2", 92 "version": 343 93 } 94 ] 95 } 96 `, 97 expectedPath: uri, 98 expectedResponse: &GetClientListsResponse{ 99 Content: []ClientList{ 100 { 101 ListContent: ListContent{ 102 CreateDate: "2023-06-06T15:58:39.225+00:00", 103 CreatedBy: "ccare2", 104 Deprecated: false, 105 ItemsCount: 1, 106 ListID: "91596_AUDITLOGSTESTLIST", 107 ListType: "CL", 108 Name: "AUDIT LOGS - TEST LIST", 109 ProductionActivationStatus: "INACTIVE", 110 ReadOnly: false, 111 Shared: false, 112 StagingActivationStatus: "INACTIVE", 113 Tags: []string{"green"}, 114 Type: "IP", 115 UpdateDate: "2023-06-06T15:58:39.225+00:00", 116 UpdatedBy: "ccare2", 117 Version: 1, 118 }, 119 }, 120 { 121 ListContent: ListContent{ 122 CreateDate: "2022-11-10T14:42:04.857+00:00", 123 CreatedBy: "ccare2", 124 Deprecated: false, 125 ItemsCount: 2, 126 ListID: "85988_ANTHONYGEOLISTOPEN", 127 ListType: "CL", 128 Name: "AnthonyGeoListOPEN", 129 Notes: "This is another Geo client list for Nov 11", 130 ProductionActivationStatus: "INACTIVE", 131 ReadOnly: false, 132 Shared: false, 133 StagingActivationStatus: "INACTIVE", 134 Tags: []string{}, 135 Type: "GEO", 136 UpdateDate: "2023-05-11T15:30:10.224+00:00", 137 UpdatedBy: "ccare2", 138 Version: 66, 139 }, 140 }, 141 { 142 ListContent: ListContent{ 143 CreateDate: "2022-10-17T13:39:25.319+00:00", 144 CreatedBy: "ccare2", 145 Deprecated: false, 146 ItemsCount: 0, 147 ListID: "85552_ANTHONYFILEHASHLIST", 148 ListType: "CL", 149 Name: "File Hash List", 150 Notes: "This is another File hash client list for Oct 17", 151 ProductionActivationStatus: "PENDING_ACTIVATION", 152 ReadOnly: false, 153 Shared: false, 154 StagingActivationStatus: "INACTIVE", 155 Tags: []string{"blue"}, 156 Type: "TLS_FINGERPRINT", 157 UpdateDate: "2023-06-05T06:56:19.004+00:00", 158 UpdatedBy: "ccare2", 159 Version: 343, 160 }, 161 }, 162 }, 163 }, 164 }, 165 "200 OK - Lists filtered by name and type": { 166 params: GetClientListsRequest{ 167 Name: "list name", 168 Type: []ClientListType{IP, GEO}, 169 }, 170 responseStatus: http.StatusOK, 171 responseBody: ` 172 { 173 "content": [ 174 { 175 "createDate": "2023-06-06T15:58:39.225+00:00", 176 "createdBy": "ccare2", 177 "deprecated": false, 178 "filePrefix": "CL", 179 "itemsCount": 1, 180 "listId": "91596_AUDITLOGSTESTLIST", 181 "listType": "CL", 182 "name": "AUDIT LOGS - TEST LIST", 183 "productionActivationStatus": "INACTIVE", 184 "readOnly": false, 185 "shared": false, 186 "stagingActivationStatus": "INACTIVE", 187 "tags": ["green"], 188 "type": "IP", 189 "updateDate": "2023-06-06T15:58:39.225+00:00", 190 "updatedBy": "ccare2", 191 "version": 1 192 } 193 ] 194 } 195 `, 196 expectedPath: fmt.Sprintf(uri+"?name=%s&type=%s&type=%s", "list+name", "IP", "GEO"), 197 expectedResponse: &GetClientListsResponse{ 198 Content: []ClientList{ 199 { 200 ListContent: ListContent{ 201 CreateDate: "2023-06-06T15:58:39.225+00:00", 202 CreatedBy: "ccare2", 203 Deprecated: false, 204 ItemsCount: 1, 205 ListID: "91596_AUDITLOGSTESTLIST", 206 ListType: "CL", 207 Name: "AUDIT LOGS - TEST LIST", 208 ProductionActivationStatus: "INACTIVE", 209 ReadOnly: false, 210 Shared: false, 211 StagingActivationStatus: "INACTIVE", 212 Tags: []string{"green"}, 213 Type: "IP", 214 UpdateDate: "2023-06-06T15:58:39.225+00:00", 215 UpdatedBy: "ccare2", 216 Version: 1, 217 }, 218 }, 219 }, 220 }, 221 }, 222 "200 OK - Lists filtered by search and query params: includeItems, includeDeprecated, includeNetworkList, page, pageSize, sort": { 223 params: GetClientListsRequest{ 224 Search: "search term", 225 IncludeItems: true, 226 IncludeDeprecated: true, 227 IncludeNetworkList: true, 228 Page: tools.IntPtr(0), 229 PageSize: tools.IntPtr(2), 230 Sort: []string{"updatedBy:desc", "value:desc"}, 231 }, 232 responseStatus: http.StatusOK, 233 responseBody: ` 234 { 235 "content": [ 236 { 237 "createDate": "2023-06-06T15:58:39.225+00:00", 238 "createdBy": "ccare2", 239 "deprecated": false, 240 "filePrefix": "CL", 241 "itemsCount": 1, 242 "listId": "91596_AUDITLOGSTESTLIST", 243 "listType": "CL", 244 "name": "AUDIT LOGS - TEST LIST", 245 "productionActivationStatus": "INACTIVE", 246 "readOnly": false, 247 "shared": false, 248 "stagingActivationStatus": "INACTIVE", 249 "tags": ["green"], 250 "type": "IP", 251 "updateDate": "2023-06-06T15:58:39.225+00:00", 252 "updatedBy": "ccare2", 253 "version": 1, 254 "items": [] 255 } 256 ] 257 }`, 258 expectedPath: fmt.Sprintf( 259 uri+"?includeDeprecated=%s&includeItems=%s&includeNetworkList=%s&page=%d&pageSize=%d&search=%s&sort=%s&sort=%s", 260 "true", "true", "true", 0, 2, "search+term", "updatedBy%3Adesc", "value%3Adesc", 261 ), 262 expectedResponse: &GetClientListsResponse{ 263 Content: []ClientList{ 264 { 265 ListContent: ListContent{ 266 CreateDate: "2023-06-06T15:58:39.225+00:00", 267 CreatedBy: "ccare2", 268 Deprecated: false, 269 ItemsCount: 1, 270 ListID: "91596_AUDITLOGSTESTLIST", 271 ListType: "CL", 272 Name: "AUDIT LOGS - TEST LIST", 273 ProductionActivationStatus: "INACTIVE", 274 ReadOnly: false, 275 Shared: false, 276 StagingActivationStatus: "INACTIVE", 277 Tags: []string{"green"}, 278 Type: "IP", 279 UpdateDate: "2023-06-06T15:58:39.225+00:00", 280 UpdatedBy: "ccare2", 281 Version: 1, 282 }, 283 Items: []ListItemContent{}, 284 }, 285 }, 286 }, 287 }, 288 "500 internal server error": { 289 params: GetClientListsRequest{}, 290 responseStatus: http.StatusInternalServerError, 291 responseBody: ` 292 { 293 "type": "internal_error", 294 "title": "Internal Server Error", 295 "detail": "Error fetching client lists", 296 "status": 500 297 }`, 298 expectedPath: uri, 299 withError: &Error{ 300 Type: "internal_error", 301 Title: "Internal Server Error", 302 Detail: "Error fetching client lists", 303 StatusCode: http.StatusInternalServerError, 304 }, 305 }, 306 } 307 308 for name, test := range tests { 309 t.Run(name, func(t *testing.T) { 310 mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 311 assert.Equal(t, test.expectedPath, r.URL.String()) 312 assert.Equal(t, http.MethodGet, r.Method) 313 w.WriteHeader(test.responseStatus) 314 _, err := w.Write([]byte(test.responseBody)) 315 assert.NoError(t, err) 316 })) 317 client := mockAPIClient(t, mockServer) 318 result, err := client.GetClientLists( 319 context.Background(), 320 test.params) 321 if test.withError != nil { 322 assert.True(t, errors.Is(err, test.withError), "want: %s; got: %s", test.withError, err) 323 return 324 } 325 require.NoError(t, err) 326 assert.Equal(t, test.expectedResponse, result) 327 }) 328 } 329 } 330 331 func TestGetClientList(t *testing.T) { 332 uri := "/client-list/v1/lists/12_AB?includeItems=true" 333 334 tests := map[string]struct { 335 params GetClientListRequest 336 responseStatus int 337 responseBody string 338 expectedPath string 339 expectedResponse *GetClientListResponse 340 withError error 341 }{ 342 "200 OK": { 343 params: GetClientListRequest{ 344 ListID: "12_AB", 345 IncludeItems: true, 346 }, 347 responseStatus: http.StatusOK, 348 responseBody: `{ 349 "createDate": "2023-06-06T15:58:39.225+00:00", 350 "createdBy": "ccare2", 351 "deprecated": false, 352 "filePrefix": "CL", 353 "itemsCount": 1, 354 "listId": "12_AB", 355 "listType": "CL", 356 "name": "AUDIT LOGS - TEST LIST", 357 "productionActivationStatus": "INACTIVE", 358 "readOnly": false, 359 "shared": false, 360 "stagingActivationStatus": "INACTIVE", 361 "productionActiveVersion": 2, 362 "stagingActiveVersion": 2, 363 "tags": ["green"], 364 "type": "IP", 365 "updateDate": "2023-06-06T15:58:39.225+00:00", 366 "updatedBy": "ccare2", 367 "version": 1, 368 "groupId": 12, 369 "groupName": "123_ABC", 370 "contractId" :"12_CO", 371 "items": [ 372 { 373 "createDate": "2022-07-12T20:14:29.189+00:00", 374 "createdBy": "ccare2", 375 "createdVersion": 9, 376 "productionStatus": "INACTIVE", 377 "stagingStatus": "PENDING_ACTIVATION", 378 "tags": [], 379 "type": "IP", 380 "updateDate": "2022-07-12T20:14:29.189+00:00", 381 "updatedBy": "ccare2", 382 "value": "7d0:1:0::0/64" 383 }, 384 { 385 "createDate": "2022-07-12T20:14:29.189+00:00", 386 "createdBy": "ccare2", 387 "createdVersion": 9, 388 "description": "Item with description, tags, expiration date", 389 "expirationDate": "2030-12-31T12:40:00.000+00:00", 390 "productionStatus": "INACTIVE", 391 "stagingStatus": "PENDING_ACTIVATION", 392 "tags": [ 393 "red", 394 "green", 395 "blue" 396 ], 397 "type": "IP", 398 "updateDate": "2022-07-12T20:14:29.189+00:00", 399 "updatedBy": "ccare2", 400 "value": "7d0:1:1::0/64" 401 } 402 ] 403 }`, 404 expectedPath: uri, 405 expectedResponse: &GetClientListResponse{ 406 ListContent: ListContent{ 407 CreateDate: "2023-06-06T15:58:39.225+00:00", 408 CreatedBy: "ccare2", 409 Deprecated: false, 410 ItemsCount: 1, 411 ListID: "12_AB", 412 ListType: "CL", 413 Name: "AUDIT LOGS - TEST LIST", 414 ProductionActivationStatus: "INACTIVE", 415 ReadOnly: false, 416 Shared: false, 417 StagingActivationStatus: "INACTIVE", 418 ProductionActiveVersion: 2, 419 StagingActiveVersion: 2, 420 Tags: []string{"green"}, 421 Type: "IP", 422 UpdateDate: "2023-06-06T15:58:39.225+00:00", 423 UpdatedBy: "ccare2", 424 Version: 1, 425 }, 426 GroupID: 12, 427 GroupName: "123_ABC", 428 ContractID: "12_CO", 429 Items: []ListItemContent{ 430 { 431 CreateDate: "2022-07-12T20:14:29.189+00:00", 432 CreatedBy: "ccare2", 433 CreatedVersion: 9, 434 ProductionStatus: "INACTIVE", 435 StagingStatus: "PENDING_ACTIVATION", 436 Tags: []string{}, 437 Type: "IP", 438 UpdateDate: "2022-07-12T20:14:29.189+00:00", 439 UpdatedBy: "ccare2", 440 Value: "7d0:1:0::0/64", 441 }, 442 { 443 CreateDate: "2022-07-12T20:14:29.189+00:00", 444 CreatedBy: "ccare2", 445 CreatedVersion: 9, 446 ProductionStatus: "INACTIVE", 447 StagingStatus: "PENDING_ACTIVATION", 448 Tags: []string{"red", "green", "blue"}, 449 Description: "Item with description, tags, expiration date", 450 ExpirationDate: "2030-12-31T12:40:00.000+00:00", 451 Type: "IP", 452 UpdateDate: "2022-07-12T20:14:29.189+00:00", 453 UpdatedBy: "ccare2", 454 Value: "7d0:1:1::0/64", 455 }, 456 }, 457 }, 458 }, 459 "500 internal server error": { 460 params: GetClientListRequest{ 461 ListID: "12_AB", 462 IncludeItems: true, 463 }, 464 responseStatus: http.StatusInternalServerError, 465 responseBody: ` 466 { 467 "type": "internal_error", 468 "title": "Internal Server Error", 469 "detail": "Error fetching client lists", 470 "status": 500 471 }`, 472 expectedPath: uri, 473 withError: &Error{ 474 Type: "internal_error", 475 Title: "Internal Server Error", 476 Detail: "Error fetching client lists", 477 StatusCode: http.StatusInternalServerError, 478 }, 479 }, 480 "validation error": { 481 params: GetClientListRequest{}, 482 withError: ErrStructValidation, 483 }, 484 } 485 486 for name, test := range tests { 487 t.Run(name, func(t *testing.T) { 488 mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 489 assert.Equal(t, test.expectedPath, r.URL.String()) 490 assert.Equal(t, http.MethodGet, r.Method) 491 w.WriteHeader(test.responseStatus) 492 _, err := w.Write([]byte(test.responseBody)) 493 assert.NoError(t, err) 494 })) 495 client := mockAPIClient(t, mockServer) 496 result, err := client.GetClientList( 497 session.ContextWithOptions( 498 context.Background(), 499 ), 500 test.params) 501 if test.withError != nil { 502 assert.True(t, errors.Is(err, test.withError), "want: %s; got: %s", test.withError, err) 503 return 504 } 505 require.NoError(t, err) 506 assert.Equal(t, test.expectedResponse, result) 507 }) 508 } 509 } 510 511 func TestUpdateClientList(t *testing.T) { 512 uri := "/client-list/v1/lists/12_12" 513 request := UpdateClientListRequest{ 514 UpdateClientList: UpdateClientList{ 515 Name: "Some New Name", 516 Tags: []string{"red"}, 517 Notes: "Updating list notes", 518 }, 519 ListID: "12_12", 520 } 521 result := UpdateClientListResponse{ 522 ContractID: "M-2CF0QRI", 523 GroupName: "Kona QA16-M-2CF0QRI", 524 GroupID: 12, 525 ListContent: ListContent{ 526 CreateDate: "2023-04-03T15:50:34.074+00:00", 527 CreatedBy: "ccare2", 528 Deprecated: false, 529 ItemsCount: 51, 530 ListID: "12_12", 531 ListType: "CL", 532 Name: "Some New Name", 533 Tags: []string{"red"}, 534 Notes: "Updating list notes", 535 ProductionActivationStatus: "INACTIVE", 536 ReadOnly: false, 537 Shared: false, 538 StagingActivationStatus: "INACTIVE", 539 ProductionActiveVersion: 2, 540 StagingActiveVersion: 2, 541 Type: "IP", 542 UpdateDate: "2023-06-15T20:28:09.047+00:00", 543 UpdatedBy: "ccare2", 544 Version: 75, 545 }, 546 } 547 548 tests := map[string]struct { 549 params UpdateClientListRequest 550 expectedRequestBody string 551 responseStatus int 552 responseBody string 553 expectedPath string 554 expectedResponse *UpdateClientListResponse 555 withError error 556 }{ 557 "200 OK": { 558 params: request, 559 expectedRequestBody: `{"name":"Some New Name","notes":"Updating list notes","tags":["red"]}`, 560 responseStatus: http.StatusOK, 561 responseBody: `{ 562 "contractId": "M-2CF0QRI", 563 "createDate": "2023-04-03T15:50:34.074+00:00", 564 "createdBy": "ccare2", 565 "deprecated": false, 566 "filePrefix": "CL", 567 "groupName": "Kona QA16-M-2CF0QRI", 568 "groupId": 12, 569 "itemsCount": 51, 570 "listId": "12_12", 571 "listType": "CL", 572 "name": "Some New Name", 573 "tags": [ "red"], 574 "notes": "Updating list notes", 575 "productionActivationStatus": "INACTIVE", 576 "readOnly": false, 577 "shared": false, 578 "stagingActivationStatus": "INACTIVE", 579 "productionActiveVersion": 2, 580 "stagingActiveVersion": 2, 581 "type": "IP", 582 "updateDate": "2023-06-15T20:28:09.047+00:00", 583 "updatedBy": "ccare2", 584 "version": 75 585 }`, 586 expectedPath: uri, 587 expectedResponse: &result, 588 }, 589 "500 internal server error": { 590 params: request, 591 responseStatus: http.StatusInternalServerError, 592 responseBody: ` 593 { 594 "type": "internal_error", 595 "title": "Internal Server Error", 596 "detail": "Error fetching client lists", 597 "status": 500 598 }`, 599 expectedPath: uri, 600 withError: &Error{ 601 Type: "internal_error", 602 Title: "Internal Server Error", 603 Detail: "Error fetching client lists", 604 StatusCode: http.StatusInternalServerError, 605 }, 606 }, 607 "validation error": { 608 params: UpdateClientListRequest{}, 609 withError: ErrStructValidation, 610 }, 611 } 612 613 for name, test := range tests { 614 t.Run(name, func(t *testing.T) { 615 mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 616 assert.Equal(t, test.expectedPath, r.URL.String()) 617 assert.Equal(t, http.MethodPut, r.Method) 618 w.WriteHeader(test.responseStatus) 619 _, err := w.Write([]byte(test.responseBody)) 620 assert.NoError(t, err) 621 622 if len(test.expectedRequestBody) > 0 { 623 body, err := ioutil.ReadAll(r.Body) 624 require.NoError(t, err) 625 assert.Equal(t, test.expectedRequestBody, string(body)) 626 } 627 })) 628 client := mockAPIClient(t, mockServer) 629 result, err := client.UpdateClientList( 630 context.Background(), 631 test.params) 632 if test.withError != nil { 633 assert.True(t, errors.Is(err, test.withError), "want: %s; got: %s", test.withError, err) 634 return 635 } 636 require.NoError(t, err) 637 assert.Equal(t, test.expectedResponse, result) 638 }) 639 } 640 } 641 func TestUpdateClientListItems(t *testing.T) { 642 uri := "/client-list/v1/lists/12_12/items" 643 request := UpdateClientListItemsRequest{ 644 ListID: "12_12", 645 UpdateClientListItems: UpdateClientListItems{ 646 Append: []ListItemPayload{ 647 { 648 Description: "Lorem Ipsum has been the industry's standard dummy text ever since the 1500s...", 649 ExpirationDate: "2026-12-26T01:32:08.375+00:00", 650 Value: "1.1.1.72", 651 }, 652 }, 653 Update: []ListItemPayload{ 654 { 655 Description: "remove exp date and tags", 656 ExpirationDate: "", 657 Tags: []string{"t"}, 658 Value: "1.1.1.45", 659 }, 660 { 661 ExpirationDate: "2028-11-26T17:32:08.375+00:00", 662 Value: "1.1.1.33", 663 }, 664 }, 665 Delete: []ListItemPayload{ 666 { 667 Value: "1.1.1.38", 668 }, 669 }, 670 }, 671 } 672 result := UpdateClientListItemsResponse{ 673 Appended: []ListItemContent{ 674 { 675 Description: "Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley", 676 ExpirationDate: "2026-12-26T01:32:08.375+00:00", 677 Tags: []string{"new tag"}, 678 Value: "1.1.1.75", 679 CreateDate: "2023-06-15T20:46:30.780+00:00", 680 CreatedBy: "ccare2", 681 CreatedVersion: 76, 682 ProductionStatus: "INACTIVE", 683 StagingStatus: "INACTIVE", 684 Type: "IP", 685 UpdateDate: "2023-06-15T20:46:30.780+00:00", 686 UpdatedBy: "ccare2", 687 }, 688 }, 689 Deleted: []ListItemContent{ 690 { 691 Value: "1.1.1.39", 692 }, 693 }, 694 Updated: []ListItemContent{ 695 { 696 Description: "remove exp date and tags", 697 Tags: []string{"t1"}, 698 Value: "1.1.1.45", 699 CreateDate: "2023-04-28T19:34:00.906+00:00", 700 CreatedBy: "ccare2", 701 CreatedVersion: 54, 702 ProductionStatus: "INACTIVE", 703 StagingStatus: "INACTIVE", 704 Type: "IP", 705 UpdateDate: "2023-06-15T20:46:30.765+00:00", 706 UpdatedBy: "ccare2", 707 }, 708 }, 709 } 710 711 tests := map[string]struct { 712 params UpdateClientListItemsRequest 713 expectedRequestBody string 714 responseStatus int 715 responseBody string 716 expectedPath string 717 expectedResponse *UpdateClientListItemsResponse 718 withError error 719 }{ 720 "200 OK": { 721 params: request, 722 expectedRequestBody: `{"append":[{"value":"1.1.1.72","tags":null,"description":"Lorem Ipsum has been the industry's standard dummy text ever since the 1500s...","expirationDate":"2026-12-26T01:32:08.375+00:00"}],"update":[{"value":"1.1.1.45","tags":["t"],"description":"remove exp date and tags","expirationDate":""},{"value":"1.1.1.33","tags":null,"description":"","expirationDate":"2028-11-26T17:32:08.375+00:00"}],"delete":[{"value":"1.1.1.38","tags":null,"description":"","expirationDate":""}]}`, 723 responseStatus: http.StatusOK, 724 responseBody: `{ 725 "appended": [ 726 { 727 "createDate": "2023-06-15T20:46:30.780+00:00", 728 "createdBy": "ccare2", 729 "createdVersion": 76, 730 "description": "Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley", 731 "expirationDate": "2026-12-26T01:32:08.375+00:00", 732 "productionStatus": "INACTIVE", 733 "stagingStatus": "INACTIVE", 734 "tags": [ 735 "new tag" 736 ], 737 "type": "IP", 738 "updateDate": "2023-06-15T20:46:30.780+00:00", 739 "updatedBy": "ccare2", 740 "value": "1.1.1.75" 741 } 742 ], 743 "deleted": [ 744 { 745 "value": "1.1.1.39" 746 } 747 ], 748 "updated": [ 749 { 750 "createDate": "2023-04-28T19:34:00.906+00:00", 751 "createdBy": "ccare2", 752 "createdVersion": 54, 753 "description": "remove exp date and tags", 754 "productionStatus": "INACTIVE", 755 "stagingStatus": "INACTIVE", 756 "tags": [ 757 "t1" 758 ], 759 "type": "IP", 760 "updateDate": "2023-06-15T20:46:30.765+00:00", 761 "updatedBy": "ccare2", 762 "value": "1.1.1.45" 763 } 764 ] 765 }`, 766 expectedPath: uri, 767 expectedResponse: &result, 768 }, 769 "500 internal server error": { 770 params: request, 771 responseStatus: http.StatusInternalServerError, 772 responseBody: ` 773 { 774 "type": "internal_error", 775 "title": "Internal Server Error", 776 "detail": "Error fetching client lists", 777 "status": 500 778 }`, 779 expectedPath: uri, 780 withError: &Error{ 781 Type: "internal_error", 782 Title: "Internal Server Error", 783 Detail: "Error fetching client lists", 784 StatusCode: http.StatusInternalServerError, 785 }, 786 }, 787 "validation error": { 788 params: UpdateClientListItemsRequest{}, 789 withError: ErrStructValidation, 790 }, 791 } 792 793 for name, test := range tests { 794 t.Run(name, func(t *testing.T) { 795 mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 796 assert.Equal(t, test.expectedPath, r.URL.String()) 797 assert.Equal(t, http.MethodPost, r.Method) 798 w.WriteHeader(test.responseStatus) 799 _, err := w.Write([]byte(test.responseBody)) 800 assert.NoError(t, err) 801 802 if len(test.expectedRequestBody) > 0 { 803 body, err := ioutil.ReadAll(r.Body) 804 require.NoError(t, err) 805 assert.Equal(t, test.expectedRequestBody, string(body)) 806 } 807 })) 808 client := mockAPIClient(t, mockServer) 809 result, err := client.UpdateClientListItems( 810 context.Background(), 811 test.params) 812 if test.withError != nil { 813 assert.True(t, errors.Is(err, test.withError), "want: %s; got: %s", test.withError, err) 814 return 815 } 816 require.NoError(t, err) 817 assert.Equal(t, test.expectedResponse, result) 818 }) 819 } 820 } 821 822 func TestCreateClientLists(t *testing.T) { 823 uri := "/client-list/v1/lists" 824 request := CreateClientListRequest{ 825 Name: "TEST LIST", 826 Type: "IP", 827 Notes: "Some notes", 828 Tags: []string{"red", "green"}, 829 ContractID: "M-2CF0QRI", 830 GroupID: 112524, 831 Items: []ListItemPayload{ 832 { 833 Value: "1.1.1.1", 834 Description: "some description", 835 Tags: []string{}, 836 ExpirationDate: "2026-12-26T01:32:08.375+00:00", 837 }, 838 }, 839 } 840 result := CreateClientListResponse{ 841 ListContent: ListContent{ 842 ListID: "123_ABC", 843 Name: "TEST LIST", 844 Type: "IP", 845 Notes: "Some notes", 846 Tags: []string{"red", "green"}, 847 }, 848 ContractID: "M-2CF0QRI", 849 GroupName: "Group A", 850 GroupID: 12, 851 Items: []ListItemContent{ 852 { 853 Value: "1.1.1.1", 854 Description: "", 855 Tags: []string{}, 856 ExpirationDate: "2026-12-26T01:32:08.375+00:00", 857 }, 858 }, 859 } 860 861 tests := map[string]struct { 862 params CreateClientListRequest 863 expectedRequestBody string 864 responseStatus int 865 responseBody string 866 expectedPath string 867 expectedResponse *CreateClientListResponse 868 withError error 869 }{ 870 "201 Created": { 871 params: request, 872 expectedRequestBody: `{"contractId":"M-2CF0QRI","groupId":112524,"name":"TEST LIST","type":"IP","notes":"Some notes","tags":["red","green"],"items":[{"value":"1.1.1.1","tags":[],"description":"some description","expirationDate":"2026-12-26T01:32:08.375+00:00"}]}`, 873 responseStatus: http.StatusCreated, 874 responseBody: `{ 875 "listId": "123_ABC", 876 "name": "TEST LIST", 877 "type": "IP", 878 "notes": "Some notes", 879 "tags": [ 880 "red", 881 "green" 882 ], 883 "contractId": "M-2CF0QRI", 884 "groupName": "Group A", 885 "groupId": 12, 886 "items": [ 887 { 888 "value": "1.1.1.1", 889 "description": "", 890 "tags": [], 891 "expirationDate": "2026-12-26T01:32:08.375+00:00" 892 } 893 ] 894 } 895 `, 896 expectedPath: uri, 897 expectedResponse: &result, 898 }, 899 "500 internal server error": { 900 params: request, 901 responseStatus: http.StatusInternalServerError, 902 responseBody: ` 903 { 904 "type": "internal_error", 905 "title": "Internal Server Error", 906 "detail": "Error fetching client lists", 907 "status": 500 908 }`, 909 expectedPath: uri, 910 withError: &Error{ 911 Type: "internal_error", 912 Title: "Internal Server Error", 913 Detail: "Error fetching client lists", 914 StatusCode: http.StatusInternalServerError, 915 }, 916 }, 917 "validation error": { 918 params: CreateClientListRequest{}, 919 withError: ErrStructValidation, 920 }, 921 } 922 923 for name, test := range tests { 924 t.Run(name, func(t *testing.T) { 925 mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 926 assert.Equal(t, test.expectedPath, r.URL.String()) 927 assert.Equal(t, http.MethodPost, r.Method) 928 w.WriteHeader(test.responseStatus) 929 _, err := w.Write([]byte(test.responseBody)) 930 assert.NoError(t, err) 931 932 if len(test.expectedRequestBody) > 0 { 933 body, err := ioutil.ReadAll(r.Body) 934 require.NoError(t, err) 935 assert.Equal(t, test.expectedRequestBody, string(body)) 936 } 937 })) 938 client := mockAPIClient(t, mockServer) 939 result, err := client.CreateClientList( 940 context.Background(), 941 test.params) 942 if test.withError != nil { 943 assert.True(t, errors.Is(err, test.withError), "want: %s; got: %s", test.withError, err) 944 return 945 } 946 require.NoError(t, err) 947 assert.Equal(t, test.expectedResponse, result) 948 }) 949 } 950 } 951 952 func TestDeleteClientLists(t *testing.T) { 953 uri := "/client-list/v1/lists/12_AB" 954 request := DeleteClientListRequest{ 955 ListID: "12_AB", 956 } 957 958 tests := map[string]struct { 959 params DeleteClientListRequest 960 responseStatus int 961 responseBody string 962 expectedPath string 963 expectedResponse *Error 964 withError error 965 }{ 966 "204 NoContent": { 967 params: request, 968 responseBody: "", 969 responseStatus: http.StatusNoContent, 970 expectedPath: uri, 971 expectedResponse: nil, 972 }, 973 "500 internal server error": { 974 params: request, 975 responseStatus: http.StatusInternalServerError, 976 responseBody: ` 977 { 978 "type": "internal_error", 979 "title": "Internal Server Error", 980 "detail": "Error fetching client lists", 981 "status": 500 982 }`, 983 expectedPath: uri, 984 withError: &Error{ 985 Type: "internal_error", 986 Title: "Internal Server Error", 987 Detail: "Error fetching client lists", 988 StatusCode: http.StatusInternalServerError, 989 }, 990 }, 991 "validation error": { 992 params: DeleteClientListRequest{}, 993 withError: ErrStructValidation, 994 }, 995 } 996 997 for name, test := range tests { 998 t.Run(name, func(t *testing.T) { 999 mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 1000 assert.Equal(t, test.expectedPath, r.URL.String()) 1001 assert.Equal(t, http.MethodDelete, r.Method) 1002 w.WriteHeader(test.responseStatus) 1003 _, err := w.Write([]byte(test.responseBody)) 1004 assert.NoError(t, err) 1005 })) 1006 client := mockAPIClient(t, mockServer) 1007 err := client.DeleteClientList( 1008 context.Background(), 1009 test.params) 1010 if test.withError != nil { 1011 assert.True(t, errors.Is(err, test.withError), "want: %s; got: %s", test.withError, err) 1012 return 1013 } 1014 require.NoError(t, err) 1015 }) 1016 } 1017 }