github.com/akamai/AkamaiOPEN-edgegrid-golang/v8@v8.1.0/pkg/edgeworkers/edgekv_items_test.go (about) 1 package edgeworkers 2 3 import ( 4 "context" 5 "errors" 6 "net/http" 7 "net/http/httptest" 8 "testing" 9 10 "github.com/stretchr/testify/require" 11 "github.com/tj/assert" 12 ) 13 14 func TestListItems(t *testing.T) { 15 tests := map[string]struct { 16 params ListItemsRequest 17 responseStatus int 18 responseBody string 19 expectedPath string 20 expectedResponse *ListItemsResponse 21 withError error 22 }{ 23 "200 OK - list edgekv items": { 24 params: ListItemsRequest{ 25 ItemsRequestParams{ 26 Network: "staging", 27 NamespaceID: "marketing", 28 GroupID: "countries", 29 }, 30 }, 31 responseStatus: http.StatusOK, 32 responseBody: ` 33 [ 34 "US", 35 "DE" 36 ] 37 `, 38 expectedPath: "/edgekv/v1/networks/staging/namespaces/marketing/groups/countries", 39 expectedResponse: &ListItemsResponse{ 40 "US", 41 "DE", 42 }, 43 }, 44 "validation - incorrect network": { 45 params: ListItemsRequest{ 46 ItemsRequestParams{ 47 Network: "stag", 48 NamespaceID: "marketing", 49 GroupID: "countries", 50 }, 51 }, 52 withError: ErrStructValidation, 53 }, 54 "validation - missing network": { 55 params: ListItemsRequest{ 56 ItemsRequestParams{ 57 NamespaceID: "marketing", 58 GroupID: "countries", 59 }, 60 }, 61 withError: ErrStructValidation, 62 }, 63 "validation - missing namespace_id": { 64 params: ListItemsRequest{ 65 ItemsRequestParams{ 66 Network: "staging", 67 GroupID: "countries", 68 }, 69 }, 70 withError: ErrStructValidation, 71 }, 72 "validation - missing group_id": { 73 params: ListItemsRequest{ 74 ItemsRequestParams{ 75 Network: "staging", 76 NamespaceID: "marketing", 77 }, 78 }, 79 withError: ErrStructValidation, 80 }, 81 "500 - internal server error": { 82 params: ListItemsRequest{ 83 ItemsRequestParams{ 84 Network: "staging", 85 NamespaceID: "marketing", 86 GroupID: "countries", 87 }, 88 }, 89 responseStatus: http.StatusInternalServerError, 90 responseBody: `{ 91 "type": "https://learn.akamai.com", 92 "title": "Internal Server Error", 93 "detail": "An internal error occurred.", 94 "instance": "/edgeKV/error-instances/1386a423-377c-4dba-b746-abe84738f5c5", 95 "status": 500, 96 "errorCode": "EKV_0000", 97 "additionalDetail": { 98 "requestId": "db6e61d461c20395" 99 } 100 }`, 101 expectedPath: "/edgekv/v1/networks/staging/namespaces/marketing/groups/countries", 102 withError: &Error{ 103 Type: "https://learn.akamai.com", 104 Title: "Internal Server Error", 105 Detail: "An internal error occurred.", 106 Instance: "/edgeKV/error-instances/1386a423-377c-4dba-b746-abe84738f5c5", 107 Status: 500, 108 ErrorCode: "EKV_0000", 109 AdditionalDetail: Additional{ 110 RequestID: "db6e61d461c20395", 111 }, 112 }, 113 }, 114 "404 - empty group": { 115 params: ListItemsRequest{ 116 ItemsRequestParams{ 117 Network: "staging", 118 NamespaceID: "marketing", 119 GroupID: "countries", 120 }, 121 }, 122 responseStatus: http.StatusNotFound, 123 responseBody: `{ 124 "type": "https://learn.akamai.com", 125 "title": "Not Found", 126 "detail": "The requested group is empty or not found.", 127 "instance": "/edgeKV/error-instances/1386a423-377c-4dba-b746-abe84738f5c5", 128 "status": 404, 129 "errorCode": "EKV_9000", 130 "additionalDetail": { 131 "requestId": "db6e61d461c20395" 132 } 133 }`, 134 expectedPath: "/edgekv/v1/networks/staging/namespaces/marketing/groups/countries", 135 withError: &Error{ 136 Type: "https://learn.akamai.com", 137 Title: "Not Found", 138 Detail: "The requested group is empty or not found.", 139 Instance: "/edgeKV/error-instances/1386a423-377c-4dba-b746-abe84738f5c5", 140 Status: 404, 141 ErrorCode: "EKV_9000", 142 AdditionalDetail: Additional{ 143 RequestID: "db6e61d461c20395", 144 }, 145 }, 146 }, 147 } 148 for name, test := range tests { 149 t.Run(name, func(t *testing.T) { 150 mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 151 assert.Equal(t, test.expectedPath, r.URL.String()) 152 assert.Equal(t, http.MethodGet, r.Method) 153 w.WriteHeader(test.responseStatus) 154 _, err := w.Write([]byte(test.responseBody)) 155 assert.NoError(t, err) 156 })) 157 client := mockAPIClient(t, mockServer) 158 result, err := client.ListItems(context.Background(), test.params) 159 if test.withError != nil { 160 assert.True(t, errors.Is(err, test.withError), "want: %s; got: %s", test.withError, err) 161 return 162 } 163 require.NoError(t, err) 164 assert.Equal(t, test.expectedResponse, result) 165 }) 166 } 167 } 168 169 func TestGetItem(t *testing.T) { 170 itemText := Item("English") 171 itemPairs := Item(` 172 { 173 "currency": "$", 174 "flag": "/us.png", 175 "name": "United States" 176 } 177 `) 178 179 tests := map[string]struct { 180 params GetItemRequest 181 responseStatus int 182 responseBody string 183 expectedPath string 184 expectedResponse *Item 185 withError error 186 }{ 187 "200 OK - get edgekv item text": { 188 params: GetItemRequest{ 189 ItemID: "GB", 190 ItemsRequestParams: ItemsRequestParams{ 191 Network: "staging", 192 NamespaceID: "marketing", 193 GroupID: "countries", 194 }, 195 }, 196 responseStatus: http.StatusOK, 197 responseBody: "English", 198 expectedPath: "/edgekv/v1/networks/staging/namespaces/marketing/groups/countries/items/GB", 199 expectedResponse: &itemText, 200 }, 201 "200 OK - get edgekv item key value pairs": { 202 params: GetItemRequest{ 203 ItemID: "US", 204 ItemsRequestParams: ItemsRequestParams{ 205 Network: "staging", 206 NamespaceID: "marketing", 207 GroupID: "countries", 208 }, 209 }, 210 responseStatus: http.StatusOK, 211 responseBody: ` 212 { 213 "currency": "$", 214 "flag": "/us.png", 215 "name": "United States" 216 } 217 `, 218 expectedPath: "/edgekv/v1/networks/staging/namespaces/marketing/groups/countries/items/US", 219 expectedResponse: &itemPairs, 220 }, 221 "validation - incorrect network": { 222 params: GetItemRequest{ 223 ItemID: "GB", 224 ItemsRequestParams: ItemsRequestParams{ 225 Network: "stagng", 226 NamespaceID: "marketing", 227 GroupID: "countries", 228 }, 229 }, 230 withError: ErrStructValidation, 231 }, 232 "validation - missing network": { 233 params: GetItemRequest{ 234 ItemID: "GB", 235 ItemsRequestParams: ItemsRequestParams{ 236 NamespaceID: "marketing", 237 GroupID: "countries", 238 }, 239 }, 240 withError: ErrStructValidation, 241 }, 242 "validation - missing namespace_id": { 243 params: GetItemRequest{ 244 ItemID: "GB", 245 ItemsRequestParams: ItemsRequestParams{ 246 Network: "staging", 247 GroupID: "countries", 248 }, 249 }, 250 withError: ErrStructValidation, 251 }, 252 "validation - missing group_id": { 253 params: GetItemRequest{ 254 ItemID: "GB", 255 ItemsRequestParams: ItemsRequestParams{ 256 Network: "staging", 257 NamespaceID: "marketing", 258 }, 259 }, 260 withError: ErrStructValidation, 261 }, 262 "validation - missing item_id": { 263 params: GetItemRequest{ 264 ItemsRequestParams: ItemsRequestParams{ 265 Network: "staging", 266 NamespaceID: "marketing", 267 GroupID: "countries", 268 }, 269 }, 270 withError: ErrStructValidation, 271 }, 272 "500 - internal server error": { 273 params: GetItemRequest{ 274 ItemID: "US", 275 ItemsRequestParams: ItemsRequestParams{ 276 Network: "staging", 277 NamespaceID: "marketing", 278 GroupID: "countries", 279 }, 280 }, 281 responseStatus: http.StatusInternalServerError, 282 responseBody: `{ 283 "type": "https://learn.akamai.com", 284 "title": "Internal Server Error", 285 "detail": "An internal error occurred.", 286 "instance": "/edgeKV/error-instances/1386a423-377c-4dba-b746-abe84738f5c5", 287 "status": 500, 288 "errorCode": "EKV_0000", 289 "additionalDetail": { 290 "requestId": "db6e61d461c20395" 291 } 292 }`, 293 expectedPath: "/edgekv/v1/networks/staging/namespaces/marketing/groups/countries/items/US", 294 withError: &Error{ 295 Type: "https://learn.akamai.com", 296 Title: "Internal Server Error", 297 Detail: "An internal error occurred.", 298 Instance: "/edgeKV/error-instances/1386a423-377c-4dba-b746-abe84738f5c5", 299 Status: 500, 300 ErrorCode: "EKV_0000", 301 AdditionalDetail: Additional{ 302 RequestID: "db6e61d461c20395", 303 }, 304 }, 305 }, 306 "404 - item doesn't exists": { 307 params: GetItemRequest{ 308 ItemID: "US", 309 ItemsRequestParams: ItemsRequestParams{ 310 Network: "staging", 311 NamespaceID: "marketing", 312 GroupID: "countries", 313 }, 314 }, 315 responseStatus: http.StatusNotFound, 316 responseBody: `{ 317 "type": "https://learn.akamai.com", 318 "title": "Not Found", 319 "detail": "Item 'GB' or group 'countries' was not found in the database.", 320 "instance": "/edgeKV/error-instances/1386a423-377c-4dba-b746-abe84738f5c5", 321 "status": 404, 322 "errorCode": "EKV_9000", 323 "additionalDetail": { 324 "requestId": "db6e61d461c20395" 325 } 326 }`, 327 expectedPath: "/edgekv/v1/networks/staging/namespaces/marketing/groups/countries/items/US", 328 withError: &Error{ 329 Type: "https://learn.akamai.com", 330 Title: "Not Found", 331 Detail: "Item 'GB' or group 'countries' was not found in the database.", 332 Instance: "/edgeKV/error-instances/1386a423-377c-4dba-b746-abe84738f5c5", 333 Status: 404, 334 ErrorCode: "EKV_9000", 335 AdditionalDetail: Additional{ 336 RequestID: "db6e61d461c20395", 337 }, 338 }, 339 }, 340 } 341 for name, test := range tests { 342 t.Run(name, func(t *testing.T) { 343 mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 344 assert.Equal(t, test.expectedPath, r.URL.String()) 345 assert.Equal(t, http.MethodGet, r.Method) 346 w.WriteHeader(test.responseStatus) 347 _, err := w.Write([]byte(test.responseBody)) 348 assert.NoError(t, err) 349 })) 350 client := mockAPIClient(t, mockServer) 351 result, err := client.GetItem(context.Background(), test.params) 352 if test.withError != nil { 353 assert.True(t, errors.Is(err, test.withError), "want: %s; got: %s", test.withError, err) 354 return 355 } 356 require.NoError(t, err) 357 assert.Equal(t, test.expectedResponse, result) 358 }) 359 } 360 } 361 362 func TestUpsertItem(t *testing.T) { 363 itemText := Item("English") 364 itemTextResponse := "Item was upserted in KV store with database 123456, namespace marketing, group countries, and key GB." 365 itemPairs := Item(` 366 { 367 "currency": "$", 368 "flag": "/us.png", 369 "name": "United States" 370 } 371 `) 372 itemPairsResponse := "Item was upserted in KV store with database 123456, namespace marketing, group countries, and key US." 373 374 tests := map[string]struct { 375 params UpsertItemRequest 376 responseStatus int 377 responseBody string 378 expectedPath string 379 expectedResponse *string 380 withError error 381 }{ 382 "200 OK - upsert edgekv item text": { 383 params: UpsertItemRequest{ 384 ItemID: "GB", 385 ItemData: itemText, 386 ItemsRequestParams: ItemsRequestParams{ 387 Network: "staging", 388 NamespaceID: "marketing", 389 GroupID: "countries", 390 }, 391 }, 392 responseStatus: http.StatusOK, 393 responseBody: "Item was upserted in KV store with database 123456, namespace marketing, group countries, and key GB.", 394 expectedPath: "/edgekv/v1/networks/staging/namespaces/marketing/groups/countries/items/GB", 395 expectedResponse: &itemTextResponse, 396 }, 397 "200 OK - upsert edgekv item key value pairs": { 398 params: UpsertItemRequest{ 399 ItemID: "US", 400 ItemData: itemPairs, 401 ItemsRequestParams: ItemsRequestParams{ 402 Network: "staging", 403 NamespaceID: "marketing", 404 GroupID: "countries", 405 }, 406 }, 407 responseStatus: http.StatusOK, 408 responseBody: "Item was upserted in KV store with database 123456, namespace marketing, group countries, and key US.", 409 expectedPath: "/edgekv/v1/networks/staging/namespaces/marketing/groups/countries/items/US", 410 expectedResponse: &itemPairsResponse, 411 }, 412 "validation - incorrect network": { 413 params: UpsertItemRequest{ 414 ItemID: "US", 415 ItemData: itemPairs, 416 ItemsRequestParams: ItemsRequestParams{ 417 Network: "staing", 418 NamespaceID: "marketing", 419 GroupID: "countries", 420 }, 421 }, 422 withError: ErrStructValidation, 423 }, 424 "validation - missing network": { 425 params: UpsertItemRequest{ 426 ItemID: "US", 427 ItemData: itemPairs, 428 ItemsRequestParams: ItemsRequestParams{ 429 NamespaceID: "marketing", 430 GroupID: "countries", 431 }, 432 }, 433 withError: ErrStructValidation, 434 }, 435 "validation - missing namespace_id": { 436 params: UpsertItemRequest{ 437 ItemID: "US", 438 ItemData: itemPairs, 439 ItemsRequestParams: ItemsRequestParams{ 440 Network: "staging", 441 GroupID: "countries", 442 }, 443 }, 444 withError: ErrStructValidation, 445 }, 446 "validation - missing group_id": { 447 params: UpsertItemRequest{ 448 ItemID: "US", 449 ItemData: itemPairs, 450 ItemsRequestParams: ItemsRequestParams{ 451 Network: "staging", 452 NamespaceID: "marketing", 453 }, 454 }, 455 withError: ErrStructValidation, 456 }, 457 "validation - missing item_id": { 458 params: UpsertItemRequest{ 459 ItemData: itemPairs, 460 ItemsRequestParams: ItemsRequestParams{ 461 Network: "staging", 462 NamespaceID: "marketing", 463 GroupID: "countries", 464 }, 465 }, 466 withError: ErrStructValidation, 467 }, 468 "validation - missing item_data": { 469 params: UpsertItemRequest{ 470 ItemID: "US", 471 ItemsRequestParams: ItemsRequestParams{ 472 Network: "staging", 473 NamespaceID: "marketing", 474 GroupID: "countries", 475 }, 476 }, 477 withError: ErrStructValidation, 478 }, 479 "500 - internal server error": { 480 params: UpsertItemRequest{ 481 ItemID: "US", 482 ItemData: itemPairs, 483 ItemsRequestParams: ItemsRequestParams{ 484 Network: "staging", 485 NamespaceID: "marketing", 486 GroupID: "countries", 487 }, 488 }, 489 responseStatus: http.StatusInternalServerError, 490 responseBody: `{ 491 "type": "https://learn.akamai.com", 492 "title": "Internal Server Error", 493 "detail": "An internal error occurred.", 494 "instance": "/edgeKV/error-instances/1386a423-377c-4dba-b746-abe84738f5c5", 495 "status": 500, 496 "errorCode": "EKV_0000", 497 "additionalDetail": { 498 "requestId": "db6e61d461c20395" 499 } 500 }`, 501 expectedPath: "/edgekv/v1/networks/staging/namespaces/marketing/groups/countries/items/US", 502 withError: &Error{ 503 Type: "https://learn.akamai.com", 504 Title: "Internal Server Error", 505 Detail: "An internal error occurred.", 506 Instance: "/edgeKV/error-instances/1386a423-377c-4dba-b746-abe84738f5c5", 507 Status: 500, 508 ErrorCode: "EKV_0000", 509 AdditionalDetail: Additional{ 510 RequestID: "db6e61d461c20395", 511 }, 512 }, 513 }, 514 } 515 for name, test := range tests { 516 t.Run(name, func(t *testing.T) { 517 mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 518 assert.Equal(t, test.expectedPath, r.URL.String()) 519 assert.Equal(t, http.MethodPut, r.Method) 520 w.WriteHeader(test.responseStatus) 521 _, err := w.Write([]byte(test.responseBody)) 522 assert.NoError(t, err) 523 })) 524 client := mockAPIClient(t, mockServer) 525 result, err := client.UpsertItem(context.Background(), test.params) 526 if test.withError != nil { 527 assert.True(t, errors.Is(err, test.withError), "want: %s; got: %s", test.withError, err) 528 return 529 } 530 require.NoError(t, err) 531 assert.Equal(t, test.expectedResponse, result) 532 }) 533 } 534 535 } 536 537 func TestDeleteItem(t *testing.T) { 538 itemDeleteResponse := "Item was marked for deletion from database, namespace marketing, group countries, and key GB." 539 540 tests := map[string]struct { 541 params DeleteItemRequest 542 responseStatus int 543 responseBody string 544 expectedPath string 545 expectedResponse *string 546 withError error 547 }{ 548 "200 OK - delete edgekv item": { 549 params: DeleteItemRequest{ 550 ItemID: "GB", 551 ItemsRequestParams: ItemsRequestParams{ 552 Network: "staging", 553 NamespaceID: "marketing", 554 GroupID: "countries", 555 }, 556 }, 557 responseStatus: http.StatusOK, 558 responseBody: "Item was marked for deletion from database, namespace marketing, group countries, and key GB.", 559 expectedPath: "/edgekv/v1/networks/staging/namespaces/marketing/groups/countries/items/GB", 560 expectedResponse: &itemDeleteResponse, 561 }, 562 "validation - incorrect network": { 563 params: DeleteItemRequest{ 564 ItemID: "GB", 565 ItemsRequestParams: ItemsRequestParams{ 566 Network: "sting", 567 NamespaceID: "marketing", 568 GroupID: "countries", 569 }, 570 }, 571 withError: ErrStructValidation, 572 }, 573 "validation - missing network": { 574 params: DeleteItemRequest{ 575 ItemID: "GB", 576 ItemsRequestParams: ItemsRequestParams{ 577 NamespaceID: "marketing", 578 GroupID: "countries", 579 }, 580 }, 581 withError: ErrStructValidation, 582 }, 583 "validation - missing namespace_id": { 584 params: DeleteItemRequest{ 585 ItemID: "GB", 586 ItemsRequestParams: ItemsRequestParams{ 587 Network: "staging", 588 GroupID: "countries", 589 }, 590 }, 591 withError: ErrStructValidation, 592 }, 593 "validation - missing group_id": { 594 params: DeleteItemRequest{ 595 ItemID: "GB", 596 ItemsRequestParams: ItemsRequestParams{ 597 Network: "staging", 598 NamespaceID: "marketing", 599 }, 600 }, 601 withError: ErrStructValidation, 602 }, 603 "validation - missing item_id": { 604 params: DeleteItemRequest{ 605 ItemsRequestParams: ItemsRequestParams{ 606 Network: "staging", 607 NamespaceID: "marketing", 608 GroupID: "countries", 609 }, 610 }, 611 withError: ErrStructValidation, 612 }, 613 "500 - internal server error": { 614 params: DeleteItemRequest{ 615 ItemID: "GB", 616 ItemsRequestParams: ItemsRequestParams{ 617 Network: "staging", 618 NamespaceID: "marketing", 619 GroupID: "countries", 620 }, 621 }, 622 responseStatus: http.StatusInternalServerError, 623 responseBody: `{ 624 "type": "https://learn.akamai.com", 625 "title": "Internal Server Error", 626 "detail": "An internal error occurred.", 627 "instance": "/edgeKV/error-instances/1386a423-377c-4dba-b746-abe84738f5c5", 628 "status": 500, 629 "errorCode": "EKV_0000", 630 "additionalDetail": { 631 "requestId": "db6e61d461c20395" 632 } 633 }`, 634 expectedPath: "/edgekv/v1/networks/staging/namespaces/marketing/groups/countries/items/GB", 635 withError: &Error{ 636 Type: "https://learn.akamai.com", 637 Title: "Internal Server Error", 638 Detail: "An internal error occurred.", 639 Instance: "/edgeKV/error-instances/1386a423-377c-4dba-b746-abe84738f5c5", 640 Status: 500, 641 ErrorCode: "EKV_0000", 642 AdditionalDetail: Additional{ 643 RequestID: "db6e61d461c20395", 644 }, 645 }, 646 }, 647 } 648 for name, test := range tests { 649 t.Run(name, func(t *testing.T) { 650 mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 651 assert.Equal(t, test.expectedPath, r.URL.String()) 652 assert.Equal(t, http.MethodDelete, r.Method) 653 w.WriteHeader(test.responseStatus) 654 _, err := w.Write([]byte(test.responseBody)) 655 assert.NoError(t, err) 656 })) 657 client := mockAPIClient(t, mockServer) 658 result, err := client.DeleteItem(context.Background(), test.params) 659 if test.withError != nil { 660 assert.True(t, errors.Is(err, test.withError), "want: %s; got: %s", test.withError, err) 661 return 662 } 663 require.NoError(t, err) 664 assert.Equal(t, test.expectedResponse, result) 665 }) 666 } 667 668 }