github.com/akamai/AkamaiOPEN-edgegrid-golang/v8@v8.1.0/pkg/papi/include_rule_test.go (about) 1 package papi 2 3 import ( 4 "context" 5 "errors" 6 "fmt" 7 "net/http" 8 "net/http/httptest" 9 "testing" 10 11 "github.com/akamai/AkamaiOPEN-edgegrid-golang/v8/pkg/tools" 12 13 "github.com/stretchr/testify/assert" 14 "github.com/stretchr/testify/require" 15 ) 16 17 func TestGetIncludeRuleTree(t *testing.T) { 18 tests := map[string]struct { 19 params GetIncludeRuleTreeRequest 20 responseStatus int 21 responseBody string 22 expectedPath string 23 expectedResponse *GetIncludeRuleTreeResponse 24 withError error 25 }{ 26 "200 OK - get include": { 27 params: GetIncludeRuleTreeRequest{ 28 IncludeID: "inc_123456", 29 IncludeVersion: 2, 30 ContractID: "test_contract", 31 GroupID: "test_group", 32 ValidateMode: "fast", 33 ValidateRules: false, 34 }, 35 responseStatus: http.StatusOK, 36 responseBody: ` 37 { 38 "accountId": "test_account", 39 "contractId": "test_contract", 40 "groupId": "test_group", 41 "includeId": "inc_123456", 42 "includeVersion": 2, 43 "includeName": "test_include", 44 "includeType": "MICROSERVICES", 45 "etag": "etag", 46 "ruleFormat": "v2020-11-02", 47 "rules": { 48 "name": "default", 49 "criteria": [], 50 "children": [ 51 { 52 "name": "Compress Text Content", 53 "criteria": [ 54 { 55 "name": "contentType", 56 "options": { 57 "matchOperator": "IS_ONE_OF", 58 "matchWildcard": true, 59 "matchCaseSensitive": false, 60 "values": [ 61 "text/html*", 62 "text/css*", 63 "application/x-javascript*" 64 ] 65 } 66 } 67 ], 68 "behaviors": [ 69 { 70 "name": "gzipResponse", 71 "options": { "behavior": "ALWAYS" } 72 } 73 ] 74 } 75 ], 76 "options": { 77 "is_secure": false 78 }, 79 "behaviors": [ 80 { 81 "name": "origin", 82 "options": { 83 "httpPort": 80, 84 "enableTrueClientIp": false, 85 "compress": true, 86 "cacheKeyHostname": "ORIGIN_HOSTNAME", 87 "forwardHostHeader": "REQUEST_HOST_HEADER", 88 "hostname": "origin.test.com", 89 "originType": "CUSTOMER" 90 } 91 }, 92 { 93 "name": "cpCode", 94 "options": { 95 "value": { 96 "id": 12345, 97 "name": "my CP code" 98 } 99 } 100 } 101 ], 102 "customOverride": { 103 "overrideId": "cbo_12345", 104 "name": "mdc" 105 }, 106 "variables": [ 107 { 108 "name": "VAR_NAME", 109 "value": "default value", 110 "description": "This is a sample Property Manager variable.", 111 "hidden": false, 112 "sensitive": false 113 } 114 ] 115 } 116 }`, 117 expectedPath: "/papi/v1/includes/inc_123456/versions/2/rules?contractId=test_contract&groupId=test_group&validateMode=fast&validateRules=false", 118 expectedResponse: &GetIncludeRuleTreeResponse{ 119 Response: Response{ 120 AccountID: "test_account", 121 ContractID: "test_contract", 122 GroupID: "test_group", 123 }, 124 IncludeID: "inc_123456", 125 IncludeVersion: 2, 126 IncludeName: "test_include", 127 IncludeType: IncludeTypeMicroServices, 128 Etag: "etag", 129 RuleFormat: "v2020-11-02", 130 Rules: Rules{ 131 Behaviors: []RuleBehavior{ 132 { 133 Name: "origin", 134 Options: RuleOptionsMap{ 135 "httpPort": float64(80), 136 "enableTrueClientIp": false, 137 "compress": true, 138 "cacheKeyHostname": "ORIGIN_HOSTNAME", 139 "forwardHostHeader": "REQUEST_HOST_HEADER", 140 "hostname": "origin.test.com", 141 "originType": "CUSTOMER", 142 }, 143 }, 144 { 145 Name: "cpCode", 146 Options: RuleOptionsMap{ 147 "value": map[string]interface{}{ 148 "id": float64(12345), 149 "name": "my CP code", 150 }, 151 }, 152 }, 153 }, 154 Children: []Rules{ 155 { 156 Behaviors: []RuleBehavior{ 157 { 158 Name: "gzipResponse", 159 Options: RuleOptionsMap{ 160 "behavior": "ALWAYS", 161 }, 162 }, 163 }, 164 Criteria: []RuleBehavior{ 165 { 166 Locked: false, 167 Name: "contentType", 168 Options: RuleOptionsMap{ 169 "matchOperator": "IS_ONE_OF", 170 "matchWildcard": true, 171 "matchCaseSensitive": false, 172 "values": []interface{}{"text/html*", "text/css*", "application/x-javascript*"}, 173 }, 174 }, 175 }, 176 Name: "Compress Text Content", 177 }, 178 }, 179 Criteria: []RuleBehavior{}, 180 Name: "default", 181 Options: RuleOptions{IsSecure: false}, 182 CustomOverride: &RuleCustomOverride{ 183 OverrideID: "cbo_12345", 184 Name: "mdc", 185 }, 186 Variables: []RuleVariable{ 187 { 188 Description: tools.StringPtr("This is a sample Property Manager variable."), 189 Hidden: false, 190 Name: "VAR_NAME", 191 Sensitive: false, 192 Value: tools.StringPtr("default value"), 193 }, 194 }, 195 }, 196 }, 197 }, 198 "200 OK - get include with ruleFormat": { 199 params: GetIncludeRuleTreeRequest{ 200 IncludeID: "inc_123456", 201 IncludeVersion: 2, 202 ContractID: "test_contract", 203 GroupID: "test_group", 204 RuleFormat: "v2020-11-02", 205 ValidateMode: "fast", 206 ValidateRules: false, 207 }, 208 responseStatus: http.StatusOK, 209 responseBody: ` 210 { 211 "accountId": "test_account", 212 "contractId": "test_contract", 213 "groupId": "test_group", 214 "includeId": "inc_123456", 215 "includeVersion": 2, 216 "includeName": "test_include", 217 "includeType": "MICROSERVICES", 218 "etag": "etag", 219 "ruleFormat": "v2020-11-02", 220 "rules": { 221 "name": "default", 222 "criteria": [], 223 "children": [ 224 { 225 "name": "Compress Text Content", 226 "criteria": [ 227 { 228 "name": "contentType", 229 "options": { 230 "matchOperator": "IS_ONE_OF", 231 "matchWildcard": true, 232 "matchCaseSensitive": false, 233 "values": [ 234 "text/html*", 235 "text/css*", 236 "application/x-javascript*" 237 ] 238 } 239 } 240 ], 241 "behaviors": [ 242 { 243 "name": "gzipResponse", 244 "options": { "behavior": "ALWAYS" } 245 } 246 ] 247 } 248 ], 249 "options": { 250 "is_secure": false 251 }, 252 "behaviors": [ 253 { 254 "name": "origin", 255 "options": { 256 "httpPort": 80, 257 "enableTrueClientIp": false, 258 "compress": true, 259 "cacheKeyHostname": "ORIGIN_HOSTNAME", 260 "forwardHostHeader": "REQUEST_HOST_HEADER", 261 "hostname": "origin.test.com", 262 "originType": "CUSTOMER" 263 } 264 }, 265 { 266 "name": "cpCode", 267 "options": { 268 "value": { 269 "id": 12345, 270 "name": "my CP code" 271 } 272 } 273 } 274 ], 275 "customOverride": { 276 "overrideId": "cbo_12345", 277 "name": "mdc" 278 }, 279 "variables": [ 280 { 281 "name": "VAR_NAME", 282 "value": "default value", 283 "description": "This is a sample Property Manager variable.", 284 "hidden": false, 285 "sensitive": false 286 } 287 ] 288 } 289 }`, 290 expectedPath: "/papi/v1/includes/inc_123456/versions/2/rules?contractId=test_contract&groupId=test_group&validateMode=fast&validateRules=false", 291 expectedResponse: &GetIncludeRuleTreeResponse{ 292 Response: Response{ 293 AccountID: "test_account", 294 ContractID: "test_contract", 295 GroupID: "test_group", 296 }, 297 IncludeID: "inc_123456", 298 IncludeVersion: 2, 299 IncludeName: "test_include", 300 IncludeType: IncludeTypeMicroServices, 301 Etag: "etag", 302 RuleFormat: "v2020-11-02", 303 Rules: Rules{ 304 Behaviors: []RuleBehavior{ 305 { 306 Name: "origin", 307 Options: RuleOptionsMap{ 308 "httpPort": float64(80), 309 "enableTrueClientIp": false, 310 "compress": true, 311 "cacheKeyHostname": "ORIGIN_HOSTNAME", 312 "forwardHostHeader": "REQUEST_HOST_HEADER", 313 "hostname": "origin.test.com", 314 "originType": "CUSTOMER", 315 }, 316 }, 317 { 318 Name: "cpCode", 319 Options: RuleOptionsMap{ 320 "value": map[string]interface{}{ 321 "id": float64(12345), 322 "name": "my CP code", 323 }, 324 }, 325 }, 326 }, 327 Children: []Rules{ 328 { 329 Behaviors: []RuleBehavior{ 330 { 331 Name: "gzipResponse", 332 Options: RuleOptionsMap{ 333 "behavior": "ALWAYS", 334 }, 335 }, 336 }, 337 Criteria: []RuleBehavior{ 338 { 339 Locked: false, 340 Name: "contentType", 341 Options: RuleOptionsMap{ 342 "matchOperator": "IS_ONE_OF", 343 "matchWildcard": true, 344 "matchCaseSensitive": false, 345 "values": []interface{}{"text/html*", "text/css*", "application/x-javascript*"}, 346 }, 347 }, 348 }, 349 Name: "Compress Text Content", 350 }, 351 }, 352 Criteria: []RuleBehavior{}, 353 Name: "default", 354 Options: RuleOptions{IsSecure: false}, 355 CustomOverride: &RuleCustomOverride{ 356 OverrideID: "cbo_12345", 357 Name: "mdc", 358 }, 359 Variables: []RuleVariable{ 360 { 361 Description: tools.StringPtr("This is a sample Property Manager variable."), 362 Hidden: false, 363 Name: "VAR_NAME", 364 Sensitive: false, 365 Value: tools.StringPtr("default value"), 366 }, 367 }, 368 }, 369 }, 370 }, 371 "500 Internal Server Error": { 372 params: GetIncludeRuleTreeRequest{ 373 IncludeID: "inc_123456", 374 IncludeVersion: 2, 375 ContractID: "test_contract", 376 GroupID: "test_group", 377 ValidateMode: "fast", 378 ValidateRules: false, 379 }, 380 responseStatus: http.StatusInternalServerError, 381 responseBody: ` 382 { 383 "type": "internal_error", 384 "title": "Internal Server Error", 385 "detail": "Error fetching rule tree", 386 "status": 500 387 }`, 388 expectedPath: "/papi/v1/includes/inc_123456/versions/2/rules?contractId=test_contract&groupId=test_group&validateMode=fast&validateRules=false", 389 withError: &Error{ 390 Type: "internal_error", 391 Title: "Internal Server Error", 392 Detail: "Error fetching rule tree", 393 StatusCode: http.StatusInternalServerError, 394 }, 395 }, 396 "validation error - missing includeId": { 397 params: GetIncludeRuleTreeRequest{ 398 IncludeVersion: 2, 399 ContractID: "test_contract", 400 GroupID: "test_group", 401 ValidateMode: "fast", 402 ValidateRules: false, 403 }, 404 withError: ErrStructValidation, 405 }, 406 "validation error - missing includeVersion": { 407 params: GetIncludeRuleTreeRequest{ 408 IncludeID: "inc_123456", 409 ContractID: "test_contract", 410 GroupID: "test_group", 411 ValidateMode: "fast", 412 ValidateRules: false, 413 }, 414 withError: ErrStructValidation, 415 }, 416 "validation error - missing contractId": { 417 params: GetIncludeRuleTreeRequest{ 418 IncludeID: "inc_123456", 419 IncludeVersion: 2, 420 GroupID: "test_group", 421 ValidateMode: "fast", 422 ValidateRules: false, 423 }, 424 withError: ErrStructValidation, 425 }, 426 "validation error - missing groupId": { 427 params: GetIncludeRuleTreeRequest{ 428 IncludeID: "inc_123456", 429 IncludeVersion: 2, 430 ContractID: "test_contract", 431 ValidateMode: "fast", 432 ValidateRules: false, 433 }, 434 withError: ErrStructValidation, 435 }, 436 "validation error - invalid validation mode": { 437 params: GetIncludeRuleTreeRequest{ 438 IncludeID: "inc_123456", 439 IncludeVersion: 2, 440 ContractID: "test_contract", 441 GroupID: "test_group", 442 ValidateMode: "test", 443 ValidateRules: false, 444 }, 445 withError: ErrStructValidation, 446 }, 447 "validation error - invalid ruleFormat": { 448 params: GetIncludeRuleTreeRequest{ 449 IncludeID: "inc_123456", 450 IncludeVersion: 2, 451 ContractID: "test_contract", 452 GroupID: "test_group", 453 RuleFormat: "invalid", 454 ValidateMode: "fast", 455 ValidateRules: false, 456 }, 457 withError: ErrStructValidation, 458 }, 459 } 460 461 for name, test := range tests { 462 t.Run(name, func(t *testing.T) { 463 mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 464 assert.Equal(t, test.expectedPath, r.URL.String()) 465 assert.Equal(t, http.MethodGet, r.Method) 466 w.WriteHeader(test.responseStatus) 467 _, err := w.Write([]byte(test.responseBody)) 468 if test.params.RuleFormat != "" { 469 assert.Equal(t, r.Header.Get("Accept"), fmt.Sprintf("application/vnd.akamai.papirules.%s+json", test.params.RuleFormat)) 470 } 471 assert.NoError(t, err) 472 })) 473 client := mockAPIClient(t, mockServer) 474 result, err := client.GetIncludeRuleTree(context.Background(), test.params) 475 if test.withError != nil { 476 assert.True(t, errors.Is(err, test.withError), "want: %s; got: %s", test.withError, err) 477 return 478 } 479 require.NoError(t, err) 480 assert.Equal(t, test.expectedResponse, result) 481 }) 482 } 483 } 484 485 func TestUpdateIncludeRuleTree(t *testing.T) { 486 tests := map[string]struct { 487 params UpdateIncludeRuleTreeRequest 488 responseStatus int 489 responseBody string 490 responseHeaders map[string]string 491 expectedPath string 492 expectedResponse *UpdateIncludeRuleTreeResponse 493 withError error 494 }{ 495 "200 OK - update rule tree": { 496 params: UpdateIncludeRuleTreeRequest{ 497 IncludeID: "inc_123456", 498 IncludeVersion: 2, 499 ContractID: "test_contract", 500 GroupID: "test_group", 501 DryRun: true, 502 ValidateMode: "fast", 503 ValidateRules: false, 504 Rules: RulesUpdate{ 505 Comments: "version comment", 506 Rules: Rules{ 507 Comments: "default comment", 508 Behaviors: []RuleBehavior{ 509 { 510 Name: "origin", 511 Options: RuleOptionsMap{ 512 "httpPort": float64(80), 513 "enableTrueClientIp": false, 514 "compress": true, 515 "cacheKeyHostname": "ORIGIN_HOSTNAME", 516 "forwardHostHeader": "REQUEST_HOST_HEADER", 517 "hostname": "origin.test.com", 518 "originType": "CUSTOMER", 519 }, 520 }, 521 { 522 Name: "cpCode", 523 Options: RuleOptionsMap{ 524 "value": map[string]interface{}{ 525 "id": float64(12345), 526 "name": "my CP code", 527 }, 528 }, 529 }, 530 }, 531 Children: []Rules{ 532 { 533 Behaviors: []RuleBehavior{ 534 { 535 Name: "gzipResponse", 536 Options: RuleOptionsMap{ 537 "behavior": "ALWAYS", 538 }, 539 }, 540 }, 541 Criteria: []RuleBehavior{ 542 { 543 Locked: false, 544 Name: "contentType", 545 Options: RuleOptionsMap{ 546 "matchOperator": "IS_ONE_OF", 547 "matchWildcard": true, 548 "matchCaseSensitive": false, 549 "values": []interface{}{"text/html*", "text/css*", "application/x-javascript*"}, 550 }, 551 }, 552 }, 553 Name: "Compress Text Content", 554 }, 555 }, 556 Criteria: []RuleBehavior{}, 557 Name: "default", 558 Options: RuleOptions{IsSecure: false}, 559 CustomOverride: &RuleCustomOverride{ 560 OverrideID: "cbo_12345", 561 Name: "mdc", 562 }, 563 Variables: []RuleVariable{ 564 { 565 Description: tools.StringPtr("This is a sample Property Manager variable."), 566 Hidden: false, 567 Name: "VAR_NAME", 568 Sensitive: false, 569 Value: tools.StringPtr("default value"), 570 }, 571 }, 572 }, 573 }, 574 }, 575 responseStatus: http.StatusOK, 576 responseHeaders: map[string]string{ 577 "x-limit-elements-per-property-limit": "3000", 578 "x-limit-elements-per-property-remaining": "3000", 579 "x-limit-max-nested-rules-per-include-limit": "4", 580 "x-limit-max-nested-rules-per-include-remaining": "4", 581 }, 582 responseBody: ` 583 { 584 "accountId": "test_account", 585 "contractId": "test_contract", 586 "groupId": "test_group", 587 "includeId": "inc_123456", 588 "includeVersion": 2, 589 "includeName": "test_include", 590 "includeType": "MICROSERVICES", 591 "etag": "etag", 592 "ruleFormat": "v2020-11-02", 593 "comments": "version comment", 594 "rules": { 595 "name": "default", 596 "comments": "default comment", 597 "criteria": [], 598 "children": [ 599 { 600 "name": "Compress Text Content", 601 "criteria": [ 602 { 603 "name": "contentType", 604 "options": { 605 "matchOperator": "IS_ONE_OF", 606 "matchWildcard": true, 607 "matchCaseSensitive": false, 608 "values": [ 609 "text/html*", 610 "text/css*", 611 "application/x-javascript*" 612 ] 613 } 614 } 615 ], 616 "behaviors": [ 617 { 618 "name": "gzipResponse", 619 "options": { "behavior": "ALWAYS" } 620 } 621 ] 622 } 623 ], 624 "options": { 625 "is_secure": false 626 }, 627 "behaviors": [ 628 { 629 "name": "origin", 630 "options": { 631 "httpPort": 80, 632 "enableTrueClientIp": false, 633 "compress": true, 634 "cacheKeyHostname": "ORIGIN_HOSTNAME", 635 "forwardHostHeader": "REQUEST_HOST_HEADER", 636 "hostname": "origin.test.com", 637 "originType": "CUSTOMER" 638 } 639 }, 640 { 641 "name": "cpCode", 642 "options": { 643 "value": { 644 "id": 12345, 645 "name": "my CP code" 646 } 647 } 648 }, 649 { 650 "name": "matchAdvanced", 651 "options": { 652 "value": { 653 "id": 12345, 654 "name": "my advanced match" 655 } 656 }, 657 "locked": true, 658 "uuid": "fd6a63bc-120a-4891-a5f2-c479765d5553", 659 "templateUuid": "bedbac99-4ce1-43a3-96cc-b84c8cd30176" 660 } 661 ], 662 "customOverride": { 663 "overrideId": "cbo_12345", 664 "name": "mdc" 665 }, 666 "templateUuid": "bedbac99-4ce1-43a3-96cc-b84c8cd30176", 667 "templateLink": "/platformtoolkit/service/ruletemplate/30582260/1?accountId=1-1TJZFB&gid=61726&ck=16.3.1.1", 668 "variables": [ 669 { 670 "name": "VAR_NAME", 671 "value": "default value", 672 "description": "This is a sample Property Manager variable.", 673 "hidden": false, 674 "sensitive": false 675 } 676 ] 677 }, 678 "errors": [ 679 { 680 "type": "https://problems.example.net/papi/v0/validation/attribute_required", 681 "errorLocation": "#/rules/behaviors/0/options/reason", 682 "detail": "The Reason ID option on the Control Access behavior is required." 683 } 684 ] 685 }`, 686 expectedPath: "/papi/v1/includes/inc_123456/versions/2/rules?contractId=test_contract&dryRun=true&groupId=test_group&validateMode=fast&validateRules=false", 687 expectedResponse: &UpdateIncludeRuleTreeResponse{ 688 Response: Response{ 689 AccountID: "test_account", 690 ContractID: "test_contract", 691 GroupID: "test_group", 692 Errors: []*Error{ 693 { 694 Type: "https://problems.example.net/papi/v0/validation/attribute_required", 695 ErrorLocation: "#/rules/behaviors/0/options/reason", 696 Detail: "The Reason ID option on the Control Access behavior is required.", 697 }, 698 }, 699 }, 700 ResponseHeaders: UpdateIncludeResponseHeaders{ 701 ElementsPerPropertyRemaining: "3000", 702 ElementsPerPropertyTotal: "3000", 703 MaxNestedRulesPerIncludeRemaining: "4", 704 MaxNestedRulesPerIncludeTotal: "4", 705 }, 706 IncludeID: "inc_123456", 707 IncludeVersion: 2, 708 IncludeName: "test_include", 709 IncludeType: IncludeTypeMicroServices, 710 Etag: "etag", 711 RuleFormat: "v2020-11-02", 712 Comments: "version comment", 713 Rules: Rules{ 714 Comments: "default comment", 715 Behaviors: []RuleBehavior{ 716 { 717 Name: "origin", 718 Options: RuleOptionsMap{ 719 "httpPort": float64(80), 720 "enableTrueClientIp": false, 721 "compress": true, 722 "cacheKeyHostname": "ORIGIN_HOSTNAME", 723 "forwardHostHeader": "REQUEST_HOST_HEADER", 724 "hostname": "origin.test.com", 725 "originType": "CUSTOMER", 726 }, 727 }, 728 { 729 Name: "cpCode", 730 Options: RuleOptionsMap{ 731 "value": map[string]interface{}{ 732 "id": float64(12345), 733 "name": "my CP code", 734 }, 735 }, 736 }, 737 { 738 Name: "matchAdvanced", 739 Options: RuleOptionsMap{ 740 "value": map[string]interface{}{ 741 "id": float64(12345), 742 "name": "my advanced match", 743 }, 744 }, 745 Locked: true, 746 UUID: "fd6a63bc-120a-4891-a5f2-c479765d5553", 747 TemplateUuid: "bedbac99-4ce1-43a3-96cc-b84c8cd30176", 748 }, 749 }, 750 Children: []Rules{ 751 { 752 Behaviors: []RuleBehavior{ 753 { 754 Name: "gzipResponse", 755 Options: RuleOptionsMap{ 756 "behavior": "ALWAYS", 757 }, 758 }, 759 }, 760 Criteria: []RuleBehavior{ 761 { 762 Locked: false, 763 Name: "contentType", 764 Options: RuleOptionsMap{ 765 "matchOperator": "IS_ONE_OF", 766 "matchWildcard": true, 767 "matchCaseSensitive": false, 768 "values": []interface{}{"text/html*", "text/css*", "application/x-javascript*"}, 769 }, 770 }, 771 }, 772 Name: "Compress Text Content", 773 }, 774 }, 775 Criteria: []RuleBehavior{}, 776 Name: "default", 777 Options: RuleOptions{IsSecure: false}, 778 CustomOverride: &RuleCustomOverride{ 779 OverrideID: "cbo_12345", 780 Name: "mdc", 781 }, 782 TemplateUuid: "bedbac99-4ce1-43a3-96cc-b84c8cd30176", 783 TemplateLink: "/platformtoolkit/service/ruletemplate/30582260/1?accountId=1-1TJZFB&gid=61726&ck=16.3.1.1", 784 Variables: []RuleVariable{ 785 { 786 Description: tools.StringPtr("This is a sample Property Manager variable."), 787 Hidden: false, 788 Name: "VAR_NAME", 789 Sensitive: false, 790 Value: tools.StringPtr("default value"), 791 }, 792 }, 793 }, 794 }, 795 }, 796 "500 Internal Server Error": { 797 params: UpdateIncludeRuleTreeRequest{ 798 IncludeID: "inc_123456", 799 IncludeVersion: 2, 800 ContractID: "test_contract", 801 GroupID: "test_group", 802 DryRun: true, 803 ValidateMode: "fast", 804 ValidateRules: false, 805 Rules: RulesUpdate{ 806 Comments: "version comment", 807 Rules: Rules{ 808 Comments: "default comment", 809 Behaviors: []RuleBehavior{ 810 { 811 Name: "origin", 812 Options: RuleOptionsMap{ 813 "httpPort": float64(80), 814 "enableTrueClientIp": false, 815 "compress": true, 816 "cacheKeyHostname": "ORIGIN_HOSTNAME", 817 "forwardHostHeader": "REQUEST_HOST_HEADER", 818 "hostname": "origin.test.com", 819 "originType": "CUSTOMER", 820 }, 821 }, 822 { 823 Name: "cpCode", 824 Options: RuleOptionsMap{ 825 "value": map[string]interface{}{ 826 "id": float64(12345), 827 "name": "my CP code", 828 }, 829 }, 830 }, 831 }, 832 Children: []Rules{ 833 { 834 Behaviors: []RuleBehavior{ 835 { 836 Name: "gzipResponse", 837 Options: RuleOptionsMap{ 838 "behavior": "ALWAYS", 839 }, 840 }, 841 }, 842 Criteria: []RuleBehavior{ 843 { 844 Locked: false, 845 Name: "contentType", 846 Options: RuleOptionsMap{ 847 "matchOperator": "IS_ONE_OF", 848 "matchWildcard": true, 849 "matchCaseSensitive": false, 850 "values": []interface{}{"text/html*", "text/css*", "application/x-javascript*"}, 851 }, 852 }, 853 }, 854 Name: "Compress Text Content", 855 }, 856 }, 857 Criteria: []RuleBehavior{}, 858 Name: "default", 859 Options: RuleOptions{IsSecure: false}, 860 CustomOverride: &RuleCustomOverride{ 861 OverrideID: "cbo_12345", 862 Name: "mdc", 863 }, 864 Variables: []RuleVariable{ 865 { 866 Description: tools.StringPtr("This is a sample Property Manager variable."), 867 Hidden: false, 868 Name: "VAR_NAME", 869 Sensitive: false, 870 Value: tools.StringPtr("default value"), 871 }, 872 }, 873 }, 874 }, 875 }, 876 responseStatus: http.StatusInternalServerError, 877 responseBody: ` 878 { 879 "type": "internal_error", 880 "title": "Internal Server Error", 881 "detail": "Error updating rule tree", 882 "status": 500 883 }`, 884 expectedPath: "/papi/v1/includes/inc_123456/versions/2/rules?contractId=test_contract&dryRun=true&groupId=test_group&validateMode=fast&validateRules=false", 885 withError: &Error{ 886 Type: "internal_error", 887 Title: "Internal Server Error", 888 Detail: "Error updating rule tree", 889 StatusCode: http.StatusInternalServerError, 890 }, 891 }, 892 "validation error - missing includeId": { 893 params: UpdateIncludeRuleTreeRequest{ 894 IncludeVersion: 2, 895 ContractID: "test_contract", 896 GroupID: "test_group", 897 DryRun: true, 898 ValidateMode: "fast", 899 ValidateRules: false, 900 Rules: RulesUpdate{ 901 Comments: "version comment", 902 Rules: Rules{ 903 Comments: "default comment", 904 Behaviors: []RuleBehavior{ 905 { 906 Name: "origin", 907 Options: RuleOptionsMap{ 908 "httpPort": float64(80), 909 "enableTrueClientIp": false, 910 "compress": true, 911 "cacheKeyHostname": "ORIGIN_HOSTNAME", 912 "forwardHostHeader": "REQUEST_HOST_HEADER", 913 "hostname": "origin.test.com", 914 "originType": "CUSTOMER", 915 }, 916 }, 917 { 918 Name: "cpCode", 919 Options: RuleOptionsMap{ 920 "value": map[string]interface{}{ 921 "id": float64(12345), 922 "name": "my CP code", 923 }, 924 }, 925 }, 926 }, 927 Children: []Rules{ 928 { 929 Behaviors: []RuleBehavior{ 930 { 931 Name: "gzipResponse", 932 Options: RuleOptionsMap{ 933 "behavior": "ALWAYS", 934 }, 935 }, 936 }, 937 Criteria: []RuleBehavior{ 938 { 939 Locked: false, 940 Name: "contentType", 941 Options: RuleOptionsMap{ 942 "matchOperator": "IS_ONE_OF", 943 "matchWildcard": true, 944 "matchCaseSensitive": false, 945 "values": []interface{}{"text/html*", "text/css*", "application/x-javascript*"}, 946 }, 947 }, 948 }, 949 Name: "Compress Text Content", 950 }, 951 }, 952 Criteria: []RuleBehavior{}, 953 Name: "default", 954 Options: RuleOptions{IsSecure: false}, 955 CustomOverride: &RuleCustomOverride{ 956 OverrideID: "cbo_12345", 957 Name: "mdc", 958 }, 959 Variables: []RuleVariable{ 960 { 961 Description: tools.StringPtr("This is a sample Property Manager variable."), 962 Hidden: false, 963 Name: "VAR_NAME", 964 Sensitive: false, 965 Value: tools.StringPtr("default value"), 966 }, 967 }, 968 }, 969 }, 970 }, 971 withError: ErrStructValidation, 972 }, 973 "validation error - missing includeVersion": { 974 params: UpdateIncludeRuleTreeRequest{ 975 IncludeID: "inc_123456", 976 ContractID: "test_contract", 977 GroupID: "test_group", 978 DryRun: true, 979 ValidateMode: "fast", 980 ValidateRules: false, 981 Rules: RulesUpdate{ 982 Comments: "version comment", 983 Rules: Rules{ 984 Comments: "default comment", 985 Behaviors: []RuleBehavior{ 986 { 987 Name: "origin", 988 Options: RuleOptionsMap{ 989 "httpPort": float64(80), 990 "enableTrueClientIp": false, 991 "compress": true, 992 "cacheKeyHostname": "ORIGIN_HOSTNAME", 993 "forwardHostHeader": "REQUEST_HOST_HEADER", 994 "hostname": "origin.test.com", 995 "originType": "CUSTOMER", 996 }, 997 }, 998 { 999 Name: "cpCode", 1000 Options: RuleOptionsMap{ 1001 "value": map[string]interface{}{ 1002 "id": float64(12345), 1003 "name": "my CP code", 1004 }, 1005 }, 1006 }, 1007 }, 1008 Children: []Rules{ 1009 { 1010 Behaviors: []RuleBehavior{ 1011 { 1012 Name: "gzipResponse", 1013 Options: RuleOptionsMap{ 1014 "behavior": "ALWAYS", 1015 }, 1016 }, 1017 }, 1018 Criteria: []RuleBehavior{ 1019 { 1020 Locked: false, 1021 Name: "contentType", 1022 Options: RuleOptionsMap{ 1023 "matchOperator": "IS_ONE_OF", 1024 "matchWildcard": true, 1025 "matchCaseSensitive": false, 1026 "values": []interface{}{"text/html*", "text/css*", "application/x-javascript*"}, 1027 }, 1028 }, 1029 }, 1030 Name: "Compress Text Content", 1031 }, 1032 }, 1033 Criteria: []RuleBehavior{}, 1034 Name: "default", 1035 Options: RuleOptions{IsSecure: false}, 1036 CustomOverride: &RuleCustomOverride{ 1037 OverrideID: "cbo_12345", 1038 Name: "mdc", 1039 }, 1040 Variables: []RuleVariable{ 1041 { 1042 Description: tools.StringPtr("This is a sample Property Manager variable."), 1043 Hidden: false, 1044 Name: "VAR_NAME", 1045 Sensitive: false, 1046 Value: tools.StringPtr("default value"), 1047 }, 1048 }, 1049 }, 1050 }, 1051 }, 1052 withError: ErrStructValidation, 1053 }, 1054 "validation error - missing contractId": { 1055 params: UpdateIncludeRuleTreeRequest{ 1056 IncludeID: "inc_123456", 1057 IncludeVersion: 2, 1058 GroupID: "test_group", 1059 DryRun: true, 1060 ValidateMode: "fast", 1061 ValidateRules: false, 1062 Rules: RulesUpdate{ 1063 Comments: "version comment", 1064 Rules: Rules{ 1065 Comments: "default comment", 1066 Behaviors: []RuleBehavior{ 1067 { 1068 Name: "origin", 1069 Options: RuleOptionsMap{ 1070 "httpPort": float64(80), 1071 "enableTrueClientIp": false, 1072 "compress": true, 1073 "cacheKeyHostname": "ORIGIN_HOSTNAME", 1074 "forwardHostHeader": "REQUEST_HOST_HEADER", 1075 "hostname": "origin.test.com", 1076 "originType": "CUSTOMER", 1077 }, 1078 }, 1079 { 1080 Name: "cpCode", 1081 Options: RuleOptionsMap{ 1082 "value": map[string]interface{}{ 1083 "id": float64(12345), 1084 "name": "my CP code", 1085 }, 1086 }, 1087 }, 1088 }, 1089 Children: []Rules{ 1090 { 1091 Behaviors: []RuleBehavior{ 1092 { 1093 Name: "gzipResponse", 1094 Options: RuleOptionsMap{ 1095 "behavior": "ALWAYS", 1096 }, 1097 }, 1098 }, 1099 Criteria: []RuleBehavior{ 1100 { 1101 Locked: false, 1102 Name: "contentType", 1103 Options: RuleOptionsMap{ 1104 "matchOperator": "IS_ONE_OF", 1105 "matchWildcard": true, 1106 "matchCaseSensitive": false, 1107 "values": []interface{}{"text/html*", "text/css*", "application/x-javascript*"}, 1108 }, 1109 }, 1110 }, 1111 Name: "Compress Text Content", 1112 }, 1113 }, 1114 Criteria: []RuleBehavior{}, 1115 Name: "default", 1116 Options: RuleOptions{IsSecure: false}, 1117 CustomOverride: &RuleCustomOverride{ 1118 OverrideID: "cbo_12345", 1119 Name: "mdc", 1120 }, 1121 Variables: []RuleVariable{ 1122 { 1123 Description: tools.StringPtr("This is a sample Property Manager variable."), 1124 Hidden: false, 1125 Name: "VAR_NAME", 1126 Sensitive: false, 1127 Value: tools.StringPtr("default value"), 1128 }, 1129 }, 1130 }, 1131 }, 1132 }, 1133 withError: ErrStructValidation, 1134 }, 1135 "validation error - missing groupId": { 1136 params: UpdateIncludeRuleTreeRequest{ 1137 IncludeID: "inc_123456", 1138 IncludeVersion: 2, 1139 ContractID: "test_contract", 1140 DryRun: true, 1141 ValidateMode: "fast", 1142 ValidateRules: false, 1143 Rules: RulesUpdate{ 1144 Comments: "version comment", 1145 Rules: Rules{ 1146 Comments: "default comment", 1147 Behaviors: []RuleBehavior{ 1148 { 1149 Name: "origin", 1150 Options: RuleOptionsMap{ 1151 "httpPort": float64(80), 1152 "enableTrueClientIp": false, 1153 "compress": true, 1154 "cacheKeyHostname": "ORIGIN_HOSTNAME", 1155 "forwardHostHeader": "REQUEST_HOST_HEADER", 1156 "hostname": "origin.test.com", 1157 "originType": "CUSTOMER", 1158 }, 1159 }, 1160 { 1161 Name: "cpCode", 1162 Options: RuleOptionsMap{ 1163 "value": map[string]interface{}{ 1164 "id": float64(12345), 1165 "name": "my CP code", 1166 }, 1167 }, 1168 }, 1169 }, 1170 Children: []Rules{ 1171 { 1172 Behaviors: []RuleBehavior{ 1173 { 1174 Name: "gzipResponse", 1175 Options: RuleOptionsMap{ 1176 "behavior": "ALWAYS", 1177 }, 1178 }, 1179 }, 1180 Criteria: []RuleBehavior{ 1181 { 1182 Locked: false, 1183 Name: "contentType", 1184 Options: RuleOptionsMap{ 1185 "matchOperator": "IS_ONE_OF", 1186 "matchWildcard": true, 1187 "matchCaseSensitive": false, 1188 "values": []interface{}{"text/html*", "text/css*", "application/x-javascript*"}, 1189 }, 1190 }, 1191 }, 1192 Name: "Compress Text Content", 1193 }, 1194 }, 1195 Criteria: []RuleBehavior{}, 1196 Name: "default", 1197 Options: RuleOptions{IsSecure: false}, 1198 CustomOverride: &RuleCustomOverride{ 1199 OverrideID: "cbo_12345", 1200 Name: "mdc", 1201 }, 1202 Variables: []RuleVariable{ 1203 { 1204 Description: tools.StringPtr("This is a sample Property Manager variable."), 1205 Hidden: false, 1206 Name: "VAR_NAME", 1207 Sensitive: false, 1208 Value: tools.StringPtr("default value"), 1209 }, 1210 }, 1211 }, 1212 }, 1213 }, 1214 withError: ErrStructValidation, 1215 }, 1216 "validation error - invalid validation mode": { 1217 params: UpdateIncludeRuleTreeRequest{ 1218 IncludeID: "inc_123456", 1219 IncludeVersion: 2, 1220 ContractID: "test_contract", 1221 GroupID: "test_group", 1222 DryRun: true, 1223 ValidateMode: "test", 1224 ValidateRules: false, 1225 Rules: RulesUpdate{ 1226 Comments: "version comment", 1227 Rules: Rules{ 1228 Comments: "default comment", 1229 Behaviors: []RuleBehavior{ 1230 { 1231 Name: "origin", 1232 Options: RuleOptionsMap{ 1233 "httpPort": float64(80), 1234 "enableTrueClientIp": false, 1235 "compress": true, 1236 "cacheKeyHostname": "ORIGIN_HOSTNAME", 1237 "forwardHostHeader": "REQUEST_HOST_HEADER", 1238 "hostname": "origin.test.com", 1239 "originType": "CUSTOMER", 1240 }, 1241 }, 1242 { 1243 Name: "cpCode", 1244 Options: RuleOptionsMap{ 1245 "value": map[string]interface{}{ 1246 "id": float64(12345), 1247 "name": "my CP code", 1248 }, 1249 }, 1250 }, 1251 }, 1252 Children: []Rules{ 1253 { 1254 Behaviors: []RuleBehavior{ 1255 { 1256 Name: "gzipResponse", 1257 Options: RuleOptionsMap{ 1258 "behavior": "ALWAYS", 1259 }, 1260 }, 1261 }, 1262 Criteria: []RuleBehavior{ 1263 { 1264 Locked: false, 1265 Name: "contentType", 1266 Options: RuleOptionsMap{ 1267 "matchOperator": "IS_ONE_OF", 1268 "matchWildcard": true, 1269 "matchCaseSensitive": false, 1270 "values": []interface{}{"text/html*", "text/css*", "application/x-javascript*"}, 1271 }, 1272 }, 1273 }, 1274 Name: "Compress Text Content", 1275 }, 1276 }, 1277 Criteria: []RuleBehavior{}, 1278 Name: "default", 1279 Options: RuleOptions{IsSecure: false}, 1280 CustomOverride: &RuleCustomOverride{ 1281 OverrideID: "cbo_12345", 1282 Name: "mdc", 1283 }, 1284 Variables: []RuleVariable{ 1285 { 1286 Description: tools.StringPtr("This is a sample Property Manager variable."), 1287 Hidden: false, 1288 Name: "VAR_NAME", 1289 Sensitive: false, 1290 Value: tools.StringPtr("default value"), 1291 }, 1292 }, 1293 }, 1294 }, 1295 }, 1296 withError: ErrStructValidation, 1297 }, 1298 } 1299 1300 for name, test := range tests { 1301 t.Run(name, func(t *testing.T) { 1302 mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 1303 assert.Equal(t, test.expectedPath, r.URL.String()) 1304 assert.Equal(t, http.MethodPut, r.Method) 1305 1306 if len(test.responseHeaders) > 0 { 1307 for header, value := range test.responseHeaders { 1308 w.Header().Set(header, value) 1309 } 1310 } 1311 w.WriteHeader(test.responseStatus) 1312 _, err := w.Write([]byte(test.responseBody)) 1313 assert.NoError(t, err) 1314 })) 1315 client := mockAPIClient(t, mockServer) 1316 result, err := client.UpdateIncludeRuleTree(context.Background(), test.params) 1317 if test.withError != nil { 1318 assert.True(t, errors.Is(err, test.withError), "want: %s; got: %s", test.withError, err) 1319 return 1320 } 1321 require.NoError(t, err) 1322 assert.Equal(t, test.expectedResponse, result) 1323 }) 1324 } 1325 }