github.com/akamai/AkamaiOPEN-edgegrid-golang/v8@v8.1.0/pkg/papi/include_test.go (about)

     1  package papi
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"io/ioutil"
     7  	"net/http"
     8  	"net/http/httptest"
     9  	"testing"
    10  
    11  	"github.com/akamai/AkamaiOPEN-edgegrid-golang/v8/pkg/tools"
    12  
    13  	"github.com/stretchr/testify/assert"
    14  	"github.com/stretchr/testify/require"
    15  )
    16  
    17  func TestListIncludes(t *testing.T) {
    18  	tests := map[string]struct {
    19  		params           ListIncludesRequest
    20  		responseStatus   int
    21  		responseBody     string
    22  		expectedPath     string
    23  		expectedResponse *ListIncludesResponse
    24  		withError        error
    25  	}{
    26  		"200 OK - list includes given contractId and groupId": {
    27  			responseStatus: http.StatusOK,
    28  			responseBody: `
    29  {
    30      "includes": {
    31          "items": [
    32              {
    33                  "accountId": "test_account",
    34                  "contractId": "test_contract",
    35                  "groupId": "test_group",
    36                  "latestVersion": 1,
    37                  "stagingVersion": null,
    38                  "productionVersion": null,
    39                  "assetId": "test_asset",
    40                  "includeId": "inc_123456",
    41                  "includeName": "test_include",
    42                  "includeType": "MICROSERVICES"
    43              },
    44              {
    45                  "accountId": "test_account_1",
    46                  "contractId": "test_contract",
    47                  "groupId": "test_group",
    48                  "latestVersion": 1,
    49                  "stagingVersion": 1,
    50                  "productionVersion": null,
    51                  "assetId": "test_asset_1",
    52                  "includeId": "inc_456789",
    53                  "includeName": "test_include_1",
    54                  "includeType": "COMMON_SETTINGS"
    55              }
    56  		]
    57  	}
    58  }`,
    59  			params: ListIncludesRequest{
    60  				ContractID: "test_contract",
    61  				GroupID:    "test_group",
    62  			},
    63  			expectedPath: "/papi/v1/includes?contractId=test_contract&groupId=test_group",
    64  			expectedResponse: &ListIncludesResponse{
    65  				Includes: IncludeItems{
    66  					Items: []Include{
    67  						{
    68  							AccountID:     "test_account",
    69  							AssetID:       "test_asset",
    70  							ContractID:    "test_contract",
    71  							GroupID:       "test_group",
    72  							IncludeID:     "inc_123456",
    73  							IncludeName:   "test_include",
    74  							IncludeType:   IncludeTypeMicroServices,
    75  							LatestVersion: 1,
    76  						},
    77  						{
    78  							AccountID:      "test_account_1",
    79  							AssetID:        "test_asset_1",
    80  							ContractID:     "test_contract",
    81  							GroupID:        "test_group",
    82  							IncludeID:      "inc_456789",
    83  							IncludeName:    "test_include_1",
    84  							IncludeType:    IncludeTypeCommonSettings,
    85  							LatestVersion:  1,
    86  							StagingVersion: tools.IntPtr(1),
    87  						},
    88  					},
    89  				},
    90  			},
    91  		},
    92  		"200 OK - list includes given only contractId": {
    93  			responseStatus: http.StatusOK,
    94  			responseBody: `
    95  {
    96      "includes": {
    97          "items": [
    98              {
    99                  "accountId": "test_account",
   100                  "contractId": "test_contract",
   101                  "groupId": "test_group",
   102                  "latestVersion": 1,
   103                  "stagingVersion": null,
   104                  "productionVersion": null,
   105                  "assetId": "test_asset",
   106                  "includeId": "inc_123456",
   107                  "includeName": "test_include",
   108                  "includeType": "MICROSERVICES"
   109              },
   110              {
   111                  "accountId": "test_account_1",
   112                  "contractId": "test_contract",
   113                  "groupId": "test_group_1",
   114                  "latestVersion": 1,
   115                  "stagingVersion": 1,
   116                  "productionVersion": null,
   117                  "assetId": "test_asset_1",
   118                  "includeId": "inc_456789",
   119                  "includeName": "test_include_1",
   120                  "includeType": "COMMON_SETTINGS"
   121              }
   122  		]
   123  	}
   124  }`,
   125  			params: ListIncludesRequest{
   126  				ContractID: "test_contract",
   127  			},
   128  			expectedPath: "/papi/v1/includes?contractId=test_contract",
   129  			expectedResponse: &ListIncludesResponse{
   130  				Includes: IncludeItems{
   131  					Items: []Include{
   132  						{
   133  							AccountID:     "test_account",
   134  							AssetID:       "test_asset",
   135  							ContractID:    "test_contract",
   136  							GroupID:       "test_group",
   137  							IncludeID:     "inc_123456",
   138  							IncludeName:   "test_include",
   139  							IncludeType:   "MICROSERVICES",
   140  							LatestVersion: 1,
   141  						},
   142  						{
   143  							AccountID:      "test_account_1",
   144  							AssetID:        "test_asset_1",
   145  							ContractID:     "test_contract",
   146  							GroupID:        "test_group_1",
   147  							IncludeID:      "inc_456789",
   148  							IncludeName:    "test_include_1",
   149  							IncludeType:    IncludeTypeCommonSettings,
   150  							LatestVersion:  1,
   151  							StagingVersion: tools.IntPtr(1),
   152  						},
   153  					},
   154  				},
   155  			},
   156  		},
   157  		"200 OK - no includes under given contractId and groupId": {
   158  			params: ListIncludesRequest{
   159  				ContractID: "test_contract",
   160  				GroupID:    "test_group",
   161  			},
   162  			responseStatus: http.StatusOK,
   163  			responseBody: `
   164  {
   165      "includes": {
   166  		"items": []
   167  	}
   168  }`,
   169  			expectedPath:     "/papi/v1/includes?contractId=test_contract&groupId=test_group",
   170  			expectedResponse: &ListIncludesResponse{Includes: IncludeItems{Items: []Include{}}},
   171  		},
   172  		"500 internal server error": {
   173  			params: ListIncludesRequest{
   174  				ContractID: "test_contract",
   175  				GroupID:    "test_group",
   176  			},
   177  			responseStatus: http.StatusInternalServerError,
   178  			responseBody: `
   179  {
   180  	"type": "internal_error",
   181      "title": "Internal Server Error",
   182      "detail": "Error fetching includes",
   183      "status": 500
   184  }`,
   185  			expectedPath: "/papi/v1/includes?contractId=test_contract&groupId=test_group",
   186  			withError: &Error{
   187  				Type:       "internal_error",
   188  				Title:      "Internal Server Error",
   189  				Detail:     "Error fetching includes",
   190  				StatusCode: http.StatusInternalServerError,
   191  			},
   192  		},
   193  		"validation error - missing contractId": {
   194  			params: ListIncludesRequest{
   195  				GroupID: "test_group",
   196  			},
   197  			withError: ErrStructValidation,
   198  		},
   199  	}
   200  	for name, test := range tests {
   201  		t.Run(name, func(t *testing.T) {
   202  			mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   203  				assert.Equal(t, test.expectedPath, r.URL.String())
   204  				assert.Equal(t, http.MethodGet, r.Method)
   205  				w.WriteHeader(test.responseStatus)
   206  				_, err := w.Write([]byte(test.responseBody))
   207  				assert.NoError(t, err)
   208  			}))
   209  			client := mockAPIClient(t, mockServer)
   210  			result, err := client.ListIncludes(context.Background(), test.params)
   211  			if test.withError != nil {
   212  				assert.True(t, errors.Is(err, test.withError), "want: %s; got: %s", test.withError, err)
   213  				return
   214  			}
   215  			require.NoError(t, err)
   216  			assert.Equal(t, test.expectedResponse, result)
   217  		})
   218  	}
   219  }
   220  
   221  func TestListIncludeParents(t *testing.T) {
   222  	tests := map[string]struct {
   223  		params           ListIncludeParentsRequest
   224  		responseStatus   int
   225  		responseBody     string
   226  		expectedPath     string
   227  		expectedResponse *ListIncludeParentsResponse
   228  		withError        error
   229  	}{
   230  		"200 OK - list include parents given includeId, contractId and groupId": {
   231  			responseStatus: http.StatusOK,
   232  			responseBody: `
   233  {
   234      "properties": {
   235          "items": [
   236              {
   237                  "accountId": "test_account",
   238                  "contractId": "test_contract",
   239                  "groupId": "test_group",
   240                  "propertyId": "prp_123456",
   241                  "propertyName": "test_property",
   242                  "stagingVersion": 1,
   243                  "productionVersion": null,
   244                  "assetId": "test_asset"
   245              }
   246          ]
   247      }
   248  }`,
   249  			params: ListIncludeParentsRequest{
   250  				ContractID: "test_contract",
   251  				GroupID:    "test_group",
   252  				IncludeID:  "inc_456789",
   253  			},
   254  			expectedPath: "/papi/v1/includes/inc_456789/parents?contractId=test_contract&groupId=test_group",
   255  			expectedResponse: &ListIncludeParentsResponse{
   256  				Properties: ParentPropertyItems{
   257  					Items: []ParentProperty{
   258  						{
   259  							AccountID:      "test_account",
   260  							AssetID:        "test_asset",
   261  							ContractID:     "test_contract",
   262  							GroupID:        "test_group",
   263  							PropertyID:     "prp_123456",
   264  							PropertyName:   "test_property",
   265  							StagingVersion: tools.IntPtr(1),
   266  						},
   267  					},
   268  				},
   269  			},
   270  		},
   271  		"200 OK - list includes given only includeId": {
   272  			responseStatus: http.StatusOK,
   273  			responseBody: `
   274  {
   275      "properties": {
   276          "items": [
   277              {
   278                  "accountId": "test_account",
   279                  "contractId": "test_contract",
   280                  "groupId": "test_group",
   281                  "propertyId": "prp_123456",
   282                  "propertyName": "test_property",
   283                  "stagingVersion": 1,
   284                  "productionVersion": null,
   285                  "assetId": "test_asset"
   286              }
   287          ]
   288      }
   289  }`,
   290  			params: ListIncludeParentsRequest{
   291  				IncludeID: "inc_456789",
   292  			},
   293  			expectedPath: "/papi/v1/includes/inc_456789/parents",
   294  			expectedResponse: &ListIncludeParentsResponse{
   295  				Properties: ParentPropertyItems{
   296  					Items: []ParentProperty{
   297  						{
   298  							AccountID:      "test_account",
   299  							AssetID:        "test_asset",
   300  							ContractID:     "test_contract",
   301  							GroupID:        "test_group",
   302  							PropertyID:     "prp_123456",
   303  							PropertyName:   "test_property",
   304  							StagingVersion: tools.IntPtr(1),
   305  						},
   306  					},
   307  				},
   308  			},
   309  		},
   310  		"200 OK - no parents for given include": {
   311  			params: ListIncludeParentsRequest{
   312  				ContractID: "test_contract",
   313  				GroupID:    "test_group",
   314  				IncludeID:  "inc_456789",
   315  			},
   316  			responseStatus: http.StatusOK,
   317  			responseBody: `
   318  {
   319      "properties": {
   320  		"items": []
   321  	}
   322  }`,
   323  			expectedPath:     "/papi/v1/includes/inc_456789/parents?contractId=test_contract&groupId=test_group",
   324  			expectedResponse: &ListIncludeParentsResponse{Properties: ParentPropertyItems{Items: []ParentProperty{}}},
   325  		},
   326  		"500 internal server error": {
   327  			params: ListIncludeParentsRequest{
   328  				ContractID: "test_contract",
   329  				GroupID:    "test_group",
   330  				IncludeID:  "inc_456789",
   331  			},
   332  			responseStatus: http.StatusInternalServerError,
   333  			responseBody: `
   334  {
   335  	"type": "internal_error",
   336      "title": "Internal Server Error",
   337      "detail": "Error fetching properties",
   338      "status": 500
   339  }`,
   340  			expectedPath: "/papi/v1/includes/inc_456789/parents?contractId=test_contract&groupId=test_group",
   341  			withError: &Error{
   342  				Type:       "internal_error",
   343  				Title:      "Internal Server Error",
   344  				Detail:     "Error fetching properties",
   345  				StatusCode: http.StatusInternalServerError,
   346  			},
   347  		},
   348  		"validation error - missing includeId": {
   349  			params: ListIncludeParentsRequest{
   350  				ContractID: "test_contract",
   351  				GroupID:    "test_group",
   352  			},
   353  			withError: ErrStructValidation,
   354  		},
   355  	}
   356  	for name, test := range tests {
   357  		t.Run(name, func(t *testing.T) {
   358  			mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   359  				assert.Equal(t, test.expectedPath, r.URL.String())
   360  				assert.Equal(t, http.MethodGet, r.Method)
   361  				w.WriteHeader(test.responseStatus)
   362  				_, err := w.Write([]byte(test.responseBody))
   363  				assert.NoError(t, err)
   364  			}))
   365  			client := mockAPIClient(t, mockServer)
   366  			result, err := client.ListIncludeParents(context.Background(), test.params)
   367  			if test.withError != nil {
   368  				assert.True(t, errors.Is(err, test.withError), "want: %s; got: %s", test.withError, err)
   369  				return
   370  			}
   371  			require.NoError(t, err)
   372  			assert.Equal(t, test.expectedResponse, result)
   373  		})
   374  	}
   375  }
   376  
   377  func TestGetInclude(t *testing.T) {
   378  	tests := map[string]struct {
   379  		params           GetIncludeRequest
   380  		responseStatus   int
   381  		responseBody     string
   382  		expectedPath     string
   383  		expectedResponse *GetIncludeResponse
   384  		withError        error
   385  	}{
   386  		"200 OK - get include given includeId, contractId and groupId": {
   387  			responseStatus: http.StatusOK,
   388  			responseBody: `
   389  {
   390      "includes": {
   391          "items": [
   392              {
   393                  "accountId": "test_account",
   394                  "contractId": "test_contract",
   395                  "groupId": "test_group",
   396                  "latestVersion": 1,
   397                  "stagingVersion": null,
   398                  "productionVersion": null,
   399  				"propertyType": "INCLUDE",
   400                  "assetId": "test_asset",
   401                  "includeId": "inc_123456",
   402                  "includeName": "test_include",
   403                  "includeType": "MICROSERVICES"
   404              }
   405  		]
   406  	}
   407  }`,
   408  			params: GetIncludeRequest{
   409  				ContractID: "test_contract",
   410  				GroupID:    "test_group",
   411  				IncludeID:  "inc_123456",
   412  			},
   413  			expectedPath: "/papi/v1/includes/inc_123456?contractId=test_contract&groupId=test_group",
   414  			expectedResponse: &GetIncludeResponse{
   415  				Includes: IncludeItems{
   416  					Items: []Include{
   417  						{
   418  							AccountID:     "test_account",
   419  							AssetID:       "test_asset",
   420  							ContractID:    "test_contract",
   421  							GroupID:       "test_group",
   422  							IncludeID:     "inc_123456",
   423  							IncludeName:   "test_include",
   424  							IncludeType:   "MICROSERVICES",
   425  							LatestVersion: 1,
   426  							PropertyType:  tools.StringPtr("INCLUDE"),
   427  						},
   428  					},
   429  				},
   430  				Include: Include{
   431  					AccountID:     "test_account",
   432  					AssetID:       "test_asset",
   433  					ContractID:    "test_contract",
   434  					GroupID:       "test_group",
   435  					IncludeID:     "inc_123456",
   436  					IncludeName:   "test_include",
   437  					IncludeType:   "MICROSERVICES",
   438  					LatestVersion: 1,
   439  					PropertyType:  tools.StringPtr("INCLUDE"),
   440  				},
   441  			},
   442  		},
   443  		"500 internal server error": {
   444  			params: GetIncludeRequest{
   445  				ContractID: "test_contract",
   446  				GroupID:    "test_group",
   447  				IncludeID:  "inc_123456",
   448  			},
   449  			responseStatus: http.StatusInternalServerError,
   450  			responseBody: `
   451  {
   452  	"type": "internal_error",
   453      "title": "Internal Server Error",
   454      "detail": "Error getting include",
   455      "status": 500
   456  }`,
   457  			expectedPath: "/papi/v1/includes/inc_123456?contractId=test_contract&groupId=test_group",
   458  			withError: &Error{
   459  				Type:       "internal_error",
   460  				Title:      "Internal Server Error",
   461  				Detail:     "Error getting include",
   462  				StatusCode: http.StatusInternalServerError,
   463  			},
   464  		},
   465  		"validation error - missing includeId": {
   466  			params: GetIncludeRequest{
   467  				ContractID: "test_contract",
   468  				GroupID:    "test_group",
   469  			},
   470  			withError: ErrStructValidation,
   471  		},
   472  		"validation error - missing contractId": {
   473  			params: GetIncludeRequest{
   474  				GroupID:   "test_group",
   475  				IncludeID: "inc_123456",
   476  			},
   477  			withError: ErrStructValidation,
   478  		},
   479  		"validation error - missing groupId": {
   480  			params: GetIncludeRequest{
   481  				ContractID: "test_contract",
   482  				IncludeID:  "inc_123456",
   483  			},
   484  			withError: ErrStructValidation,
   485  		},
   486  	}
   487  	for name, test := range tests {
   488  		t.Run(name, func(t *testing.T) {
   489  			mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   490  				assert.Equal(t, test.expectedPath, r.URL.String())
   491  				assert.Equal(t, http.MethodGet, r.Method)
   492  				w.WriteHeader(test.responseStatus)
   493  				_, err := w.Write([]byte(test.responseBody))
   494  				assert.NoError(t, err)
   495  			}))
   496  			client := mockAPIClient(t, mockServer)
   497  			result, err := client.GetInclude(context.Background(), test.params)
   498  			if test.withError != nil {
   499  				assert.True(t, errors.Is(err, test.withError), "want: %s; got: %s", test.withError, err)
   500  				return
   501  			}
   502  			require.NoError(t, err)
   503  			assert.Equal(t, test.expectedResponse, result)
   504  		})
   505  	}
   506  }
   507  
   508  func TestCreateInclude(t *testing.T) {
   509  	tests := map[string]struct {
   510  		params              CreateIncludeRequest
   511  		expectedRequestBody string
   512  		responseStatus      int
   513  		responseBody        string
   514  		responseHeaders     map[string]string
   515  		expectedPath        string
   516  		expectedResponse    *CreateIncludeResponse
   517  		withError           error
   518  	}{
   519  		"200 OK - create include": {
   520  			expectedRequestBody: `{"includeName":"test_include","includeType":"MICROSERVICES","productId":"test_product","ruleFormat":"test_rule_format"}`,
   521  			responseStatus:      http.StatusCreated,
   522  			responseBody: `
   523  {
   524  	"includeLink": "/papi/v1/includes/inc_123456?contractId=test_contract&groupId=test_group"
   525  }`,
   526  			responseHeaders: map[string]string{
   527  				"x-limit-includes-per-contract-limit":     "500",
   528  				"x-limit-includes-per-contract-remaining": "499",
   529  			},
   530  			params: CreateIncludeRequest{
   531  				ContractID:  "test_contract",
   532  				GroupID:     "test_group",
   533  				IncludeName: "test_include",
   534  				IncludeType: IncludeTypeMicroServices,
   535  				ProductID:   "test_product",
   536  				RuleFormat:  "test_rule_format",
   537  			},
   538  			expectedPath: "/papi/v1/includes?contractId=test_contract&groupId=test_group",
   539  			expectedResponse: &CreateIncludeResponse{
   540  				IncludeID:   "inc_123456",
   541  				IncludeLink: "/papi/v1/includes/inc_123456?contractId=test_contract&groupId=test_group",
   542  				ResponseHeaders: CreateIncludeResponseHeaders{
   543  					IncludesLimitTotal:     "500",
   544  					IncludesLimitRemaining: "499",
   545  				},
   546  			},
   547  		},
   548  		"200 OK - create include with clone": {
   549  			expectedRequestBody: `{"includeName":"test_include","includeType":"MICROSERVICES","productId":"test_product","cloneFrom":{"includeId":"inc_456789","version":1}}`,
   550  			responseStatus:      http.StatusCreated,
   551  			responseBody: `
   552  {
   553  	"includeLink": "/papi/v1/includes/inc_123456?contractId=test_contract&groupId=test_group"
   554  }`,
   555  			responseHeaders: map[string]string{
   556  				"x-limit-includes-per-contract-limit":     "700",
   557  				"x-limit-includes-per-contract-remaining": "654",
   558  			},
   559  			params: CreateIncludeRequest{
   560  				ContractID:  "test_contract",
   561  				GroupID:     "test_group",
   562  				IncludeName: "test_include",
   563  				IncludeType: IncludeTypeMicroServices,
   564  				ProductID:   "test_product",
   565  				CloneIncludeFrom: &CloneIncludeFrom{
   566  					IncludeID: "inc_456789",
   567  					Version:   1,
   568  				},
   569  			},
   570  			expectedPath: "/papi/v1/includes?contractId=test_contract&groupId=test_group",
   571  			expectedResponse: &CreateIncludeResponse{
   572  				IncludeID:   "inc_123456",
   573  				IncludeLink: "/papi/v1/includes/inc_123456?contractId=test_contract&groupId=test_group",
   574  				ResponseHeaders: CreateIncludeResponseHeaders{
   575  					IncludesLimitTotal:     "700",
   576  					IncludesLimitRemaining: "654",
   577  				},
   578  			},
   579  		},
   580  		"500 internal server error": {
   581  			params: CreateIncludeRequest{
   582  				ContractID:  "test_contract",
   583  				GroupID:     "test_group",
   584  				IncludeName: "test_include",
   585  				IncludeType: IncludeTypeMicroServices,
   586  				ProductID:   "test_product",
   587  				RuleFormat:  "test_rule_format",
   588  			},
   589  			responseStatus: http.StatusInternalServerError,
   590  			responseBody: `
   591  {
   592  	"type": "internal_error",
   593      "title": "Internal Server Error",
   594      "detail": "Error creating include",
   595      "status": 500
   596  }`,
   597  			expectedPath: "/papi/v1/includes?contractId=test_contract&groupId=test_group",
   598  			withError: &Error{
   599  				Type:       "internal_error",
   600  				Title:      "Internal Server Error",
   601  				Detail:     "Error creating include",
   602  				StatusCode: http.StatusInternalServerError,
   603  			},
   604  		},
   605  		"validation error - missing productId": {
   606  			params: CreateIncludeRequest{
   607  				ContractID:  "test_contract",
   608  				GroupID:     "test_group",
   609  				IncludeName: "test_include",
   610  				IncludeType: IncludeTypeMicroServices,
   611  				RuleFormat:  "test_rule_format",
   612  			},
   613  			withError: ErrStructValidation,
   614  		},
   615  		"validation error - missing contractId": {
   616  			params: CreateIncludeRequest{
   617  				GroupID:     "test_group",
   618  				IncludeName: "test_include",
   619  				IncludeType: IncludeTypeMicroServices,
   620  				ProductID:   "test_product",
   621  				RuleFormat:  "test_rule_format",
   622  			},
   623  			withError: ErrStructValidation,
   624  		},
   625  		"validation error - missing groupId": {
   626  			params: CreateIncludeRequest{
   627  				ContractID:  "test_contract",
   628  				IncludeName: "test_include",
   629  				IncludeType: IncludeTypeMicroServices,
   630  				ProductID:   "test_product",
   631  				RuleFormat:  "test_rule_format",
   632  			},
   633  			withError: ErrStructValidation,
   634  		},
   635  		"validation error - missing includeName": {
   636  			params: CreateIncludeRequest{
   637  				ContractID:  "test_contract",
   638  				GroupID:     "test_group",
   639  				IncludeType: IncludeTypeMicroServices,
   640  				ProductID:   "test_product",
   641  				RuleFormat:  "test_rule_format",
   642  			},
   643  			withError: ErrStructValidation,
   644  		},
   645  		"validation error - missing includeType": {
   646  			params: CreateIncludeRequest{
   647  				ContractID:  "test_contract",
   648  				GroupID:     "test_group",
   649  				IncludeName: "test_include",
   650  				ProductID:   "test_product",
   651  				RuleFormat:  "test_rule_format",
   652  			},
   653  			withError: ErrStructValidation,
   654  		},
   655  		"validation error - incorrect includeType": {
   656  			params: CreateIncludeRequest{
   657  				ContractID:  "test_contract",
   658  				GroupID:     "test_group",
   659  				IncludeName: "test_include",
   660  				IncludeType: "test",
   661  				ProductID:   "test_product",
   662  				RuleFormat:  "test_rule_format",
   663  			},
   664  			withError: ErrStructValidation,
   665  		},
   666  		"validation error - cloneFrom - missing includeId": {
   667  			params: CreateIncludeRequest{
   668  				ContractID:  "test_contract",
   669  				GroupID:     "test_group",
   670  				IncludeName: "test_include",
   671  				IncludeType: IncludeTypeMicroServices,
   672  				ProductID:   "test_product",
   673  				CloneIncludeFrom: &CloneIncludeFrom{
   674  					Version: 1,
   675  				},
   676  			},
   677  			withError: ErrStructValidation,
   678  		},
   679  		"validation error - cloneFrom - missing version": {
   680  			params: CreateIncludeRequest{
   681  				ContractID:  "test_contract",
   682  				GroupID:     "test_group",
   683  				IncludeName: "test_include",
   684  				IncludeType: IncludeTypeMicroServices,
   685  				ProductID:   "test_product",
   686  				CloneIncludeFrom: &CloneIncludeFrom{
   687  					IncludeID: "inc_123456",
   688  				},
   689  			},
   690  			withError: ErrStructValidation,
   691  		},
   692  	}
   693  	for name, test := range tests {
   694  		t.Run(name, func(t *testing.T) {
   695  			mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   696  				assert.Equal(t, test.expectedPath, r.URL.String())
   697  				assert.Equal(t, http.MethodPost, r.Method)
   698  
   699  				if len(test.responseHeaders) > 0 {
   700  					for header, value := range test.responseHeaders {
   701  						w.Header().Set(header, value)
   702  					}
   703  				}
   704  				w.WriteHeader(test.responseStatus)
   705  				_, err := w.Write([]byte(test.responseBody))
   706  				assert.NoError(t, err)
   707  
   708  				if len(test.expectedRequestBody) > 0 {
   709  					body, err := ioutil.ReadAll(r.Body)
   710  					require.NoError(t, err)
   711  					assert.Equal(t, test.expectedRequestBody, string(body))
   712  				}
   713  			}))
   714  			client := mockAPIClient(t, mockServer)
   715  			result, err := client.CreateInclude(context.Background(), test.params)
   716  			if test.withError != nil {
   717  				assert.True(t, errors.Is(err, test.withError), "want: %s; got: %s", test.withError, err)
   718  				return
   719  			}
   720  			require.NoError(t, err)
   721  			assert.Equal(t, test.expectedResponse, result)
   722  		})
   723  	}
   724  }
   725  
   726  func TestDeleteInclude(t *testing.T) {
   727  	tests := map[string]struct {
   728  		params           DeleteIncludeRequest
   729  		responseStatus   int
   730  		responseBody     string
   731  		expectedPath     string
   732  		expectedResponse *DeleteIncludeResponse
   733  		withError        error
   734  	}{
   735  		"200 OK - delete given includeId, contractId and groupId": {
   736  			responseStatus: http.StatusOK,
   737  			responseBody: `
   738  {
   739  	"message": "Deletion Successful."
   740  }`,
   741  			params: DeleteIncludeRequest{
   742  				ContractID: "test_contract",
   743  				GroupID:    "test_group",
   744  				IncludeID:  "inc_123456",
   745  			},
   746  			expectedPath: "/papi/v1/includes/inc_123456?contractId=test_contract&groupId=test_group",
   747  			expectedResponse: &DeleteIncludeResponse{
   748  				Message: "Deletion Successful.",
   749  			},
   750  		},
   751  		"200 OK - delete given only includeId": {
   752  			responseStatus: http.StatusOK,
   753  			responseBody: `
   754  {
   755  	"message": "Deletion Successful."
   756  }`,
   757  			params: DeleteIncludeRequest{
   758  				IncludeID: "inc_123456",
   759  			},
   760  			expectedPath: "/papi/v1/includes/inc_123456",
   761  			expectedResponse: &DeleteIncludeResponse{
   762  				Message: "Deletion Successful.",
   763  			},
   764  		},
   765  		"500 internal server error": {
   766  			params: DeleteIncludeRequest{
   767  				ContractID: "test_contract",
   768  				GroupID:    "test_group",
   769  				IncludeID:  "inc_123456",
   770  			},
   771  			responseStatus: http.StatusInternalServerError,
   772  			responseBody: `
   773  {
   774  	"type": "internal_error",
   775  	"title": "Internal Server Error",
   776  	"detail": "Error deleting include",
   777  	"status": 500
   778  }`,
   779  			expectedPath: "/papi/v1/includes/inc_123456?contractId=test_contract&groupId=test_group",
   780  			withError: &Error{
   781  				Type:       "internal_error",
   782  				Title:      "Internal Server Error",
   783  				Detail:     "Error deleting include",
   784  				StatusCode: http.StatusInternalServerError,
   785  			},
   786  		},
   787  		"validation error - missing includeId": {
   788  			params: DeleteIncludeRequest{
   789  				ContractID: "test_contract",
   790  				GroupID:    "test_group",
   791  			},
   792  			withError: ErrStructValidation,
   793  		},
   794  	}
   795  	for name, test := range tests {
   796  		t.Run(name, func(t *testing.T) {
   797  			mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   798  				assert.Equal(t, test.expectedPath, r.URL.String())
   799  				assert.Equal(t, http.MethodDelete, r.Method)
   800  				w.WriteHeader(test.responseStatus)
   801  				_, err := w.Write([]byte(test.responseBody))
   802  				assert.NoError(t, err)
   803  			}))
   804  			client := mockAPIClient(t, mockServer)
   805  			result, err := client.DeleteInclude(context.Background(), test.params)
   806  			if test.withError != nil {
   807  				assert.True(t, errors.Is(err, test.withError), "want: %s; got: %s", test.withError, err)
   808  				return
   809  			}
   810  			require.NoError(t, err)
   811  			assert.Equal(t, test.expectedResponse, result)
   812  		})
   813  	}
   814  }