github.com/akamai/AkamaiOPEN-edgegrid-golang/v8@v8.1.0/pkg/papi/include_activations_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/stretchr/testify/assert"
    12  	"github.com/stretchr/testify/require"
    13  )
    14  
    15  func TestActivateInclude(t *testing.T) {
    16  	tests := map[string]struct {
    17  		params              ActivateIncludeRequest
    18  		expectedRequestBody string
    19  		responseStatus      int
    20  		responseBody        string
    21  		expectedPath        string
    22  		expectedResponse    *ActivationIncludeResponse
    23  		withError           error
    24  		assertError         func(*testing.T, error)
    25  	}{
    26  		"201 Activate include acknowledging all the warnings": {
    27  			params: ActivateIncludeRequest{
    28  				IncludeID:              "inc_12345",
    29  				Version:                4,
    30  				Network:                ActivationNetworkStaging,
    31  				Note:                   "test activation",
    32  				NotifyEmails:           []string{"jbond@example.com"},
    33  				AcknowledgeAllWarnings: true,
    34  			},
    35  			expectedRequestBody: `{"acknowledgeAllWarnings":true,"activationType":"ACTIVATE","ignoreHttpErrors":true,"includeVersion":4,"network":"STAGING","note":"test activation","notifyEmails":["jbond@example.com"]}`,
    36  			expectedPath:        "/papi/v1/includes/inc_12345/activations",
    37  			responseStatus:      http.StatusCreated,
    38  			responseBody: `
    39  {
    40      "activationLink": "/papi/v1/includes/inc_12345/activations/temporary-activation-id"
    41  }`,
    42  			expectedResponse: &ActivationIncludeResponse{
    43  				ActivationID:   "temporary-activation-id",
    44  				ActivationLink: "/papi/v1/includes/inc_12345/activations/temporary-activation-id",
    45  			},
    46  		},
    47  		"201 Activate include": {
    48  			params: ActivateIncludeRequest{
    49  				IncludeID:    "inc_12345",
    50  				Version:      4,
    51  				Network:      ActivationNetworkStaging,
    52  				Note:         "test activation",
    53  				NotifyEmails: []string{"jbond@example.com"},
    54  			},
    55  			expectedRequestBody: `{"acknowledgeAllWarnings":false,"activationType":"ACTIVATE","ignoreHttpErrors":true,"includeVersion":4,"network":"STAGING","note":"test activation","notifyEmails":["jbond@example.com"]}`,
    56  			expectedPath:        "/papi/v1/includes/inc_12345/activations",
    57  			responseStatus:      http.StatusCreated,
    58  			responseBody: `
    59  {
    60      "activationLink": "/papi/v1/includes/inc_12345/activations/temporary-activation-id"
    61  }`,
    62  			expectedResponse: &ActivationIncludeResponse{
    63  				ActivationID:   "temporary-activation-id",
    64  				ActivationLink: "/papi/v1/includes/inc_12345/activations/temporary-activation-id",
    65  			},
    66  		},
    67  		"201 Activate include with ComplianceRecord None": {
    68  			params: ActivateIncludeRequest{
    69  				IncludeID:    "inc_12345",
    70  				Version:      4,
    71  				Network:      ActivationNetworkProduction,
    72  				Note:         "test activation",
    73  				NotifyEmails: []string{"jbond@example.com"},
    74  				ComplianceRecord: &ComplianceRecordNone{
    75  					CustomerEmail:  "sb@akamai.com",
    76  					PeerReviewedBy: "sb@akamai.com",
    77  					UnitTested:     true,
    78  					TicketID:       "123",
    79  				},
    80  			},
    81  			expectedRequestBody: `{"acknowledgeAllWarnings":false,"activationType":"ACTIVATE","ignoreHttpErrors":true,"includeVersion":4,"network":"PRODUCTION","note":"test activation","notifyEmails":["jbond@example.com"], "complianceRecord":{"customerEmail":"sb@akamai.com", "noncomplianceReason":"NONE", "peerReviewedBy":"sb@akamai.com", "unitTested":true, "ticketId":"123"}}`,
    82  			expectedPath:        "/papi/v1/includes/inc_12345/activations",
    83  			responseStatus:      http.StatusCreated,
    84  			responseBody: `
    85  {
    86      "activationLink": "/papi/v1/includes/inc_12345/activations/temporary-activation-id"
    87  }`,
    88  			expectedResponse: &ActivationIncludeResponse{
    89  				ActivationID:   "temporary-activation-id",
    90  				ActivationLink: "/papi/v1/includes/inc_12345/activations/temporary-activation-id",
    91  			},
    92  		},
    93  		"201 Activate include with ComplianceRecord Other": {
    94  			params: ActivateIncludeRequest{
    95  				IncludeID:    "inc_12345",
    96  				Version:      4,
    97  				Network:      ActivationNetworkProduction,
    98  				Note:         "test activation",
    99  				NotifyEmails: []string{"jbond@example.com"},
   100  				ComplianceRecord: &ComplianceRecordOther{
   101  					OtherNoncomplianceReason: "some other reason",
   102  					TicketID:                 "123",
   103  				},
   104  			},
   105  			expectedRequestBody: `{"acknowledgeAllWarnings":false,"activationType":"ACTIVATE","ignoreHttpErrors":true,"includeVersion":4,"network":"PRODUCTION","note":"test activation","notifyEmails":["jbond@example.com"], "complianceRecord":{"otherNoncomplianceReason":"some other reason", "noncomplianceReason":"OTHER", "ticketId":"123"}}`,
   106  			expectedPath:        "/papi/v1/includes/inc_12345/activations",
   107  			responseStatus:      http.StatusCreated,
   108  			responseBody: `
   109  {
   110      "activationLink": "/papi/v1/includes/inc_12345/activations/temporary-activation-id"
   111  }`,
   112  			expectedResponse: &ActivationIncludeResponse{
   113  				ActivationID:   "temporary-activation-id",
   114  				ActivationLink: "/papi/v1/includes/inc_12345/activations/temporary-activation-id",
   115  			},
   116  		},
   117  		"201 Activate include with ComplianceRecord No_Production_Traffic": {
   118  			params: ActivateIncludeRequest{
   119  				IncludeID:    "inc_12345",
   120  				Version:      4,
   121  				Network:      ActivationNetworkProduction,
   122  				Note:         "test activation",
   123  				NotifyEmails: []string{"jbond@example.com"},
   124  				ComplianceRecord: &ComplianceRecordNoProductionTraffic{
   125  					TicketID: "123",
   126  				},
   127  			},
   128  			expectedRequestBody: `{"acknowledgeAllWarnings":false,"activationType":"ACTIVATE","ignoreHttpErrors":true,"includeVersion":4,"network":"PRODUCTION","note":"test activation","notifyEmails":["jbond@example.com"], "complianceRecord":{"noncomplianceReason":"NO_PRODUCTION_TRAFFIC", "ticketId":"123"}}`,
   129  			expectedPath:        "/papi/v1/includes/inc_12345/activations",
   130  			responseStatus:      http.StatusCreated,
   131  			responseBody: `
   132  {
   133      "activationLink": "/papi/v1/includes/inc_12345/activations/temporary-activation-id"
   134  }`,
   135  			expectedResponse: &ActivationIncludeResponse{
   136  				ActivationID:   "temporary-activation-id",
   137  				ActivationLink: "/papi/v1/includes/inc_12345/activations/temporary-activation-id",
   138  			},
   139  		},
   140  		"201 Activate include with ComplianceRecord Emergency": {
   141  			params: ActivateIncludeRequest{
   142  				IncludeID:    "inc_12345",
   143  				Version:      4,
   144  				Network:      ActivationNetworkProduction,
   145  				Note:         "test activation",
   146  				NotifyEmails: []string{"jbond@example.com"},
   147  				ComplianceRecord: &ComplianceRecordEmergency{
   148  					TicketID: "123",
   149  				},
   150  			},
   151  			expectedRequestBody: `{"acknowledgeAllWarnings":false,"activationType":"ACTIVATE","ignoreHttpErrors":true,"includeVersion":4,"network":"PRODUCTION","note":"test activation","notifyEmails":["jbond@example.com"], "complianceRecord":{"noncomplianceReason":"EMERGENCY", "ticketId":"123"}}`,
   152  			expectedPath:        "/papi/v1/includes/inc_12345/activations",
   153  			responseStatus:      http.StatusCreated,
   154  			responseBody: `
   155  {
   156      "activationLink": "/papi/v1/includes/inc_12345/activations/temporary-activation-id"
   157  }`,
   158  			expectedResponse: &ActivationIncludeResponse{
   159  				ActivationID:   "temporary-activation-id",
   160  				ActivationLink: "/papi/v1/includes/inc_12345/activations/temporary-activation-id",
   161  			},
   162  		},
   163  		"500 internal server error": {
   164  			params: ActivateIncludeRequest{
   165  				IncludeID:              "inc_12345",
   166  				Version:                4,
   167  				Network:                ActivationNetworkStaging,
   168  				Note:                   "test activation",
   169  				NotifyEmails:           []string{"jbond@example.com"},
   170  				AcknowledgeAllWarnings: true,
   171  			},
   172  			expectedPath:   "/papi/v1/includes/inc_12345/activations",
   173  			responseStatus: http.StatusInternalServerError,
   174  			responseBody: `
   175  		{
   176  			"type": "internal_error",
   177  		   "title": "Internal Server Error",
   178  		   "detail": "Error getting include",
   179  		   "status": 500
   180  		}`,
   181  			withError: &Error{
   182  				Type:       "internal_error",
   183  				Title:      "Internal Server Error",
   184  				Detail:     "Error getting include",
   185  				StatusCode: http.StatusInternalServerError,
   186  			},
   187  		},
   188  		"validation error - missing include id": {
   189  			params: ActivateIncludeRequest{
   190  				Version:      4,
   191  				Network:      ActivationNetworkStaging,
   192  				NotifyEmails: []string{"jbond@example.com"},
   193  			},
   194  			withError: ErrStructValidation,
   195  		},
   196  		"validation error - missing version": {
   197  			params: ActivateIncludeRequest{
   198  				IncludeID:    "inc_12345",
   199  				Network:      ActivationNetworkStaging,
   200  				NotifyEmails: []string{"jbond@example.com"},
   201  			},
   202  			withError: ErrStructValidation,
   203  		},
   204  		"validation error - missing network": {
   205  			params: ActivateIncludeRequest{
   206  				IncludeID:    "inc_12345",
   207  				Version:      4,
   208  				NotifyEmails: []string{"jbond@example.com"},
   209  			},
   210  			withError: ErrStructValidation,
   211  		},
   212  		"validation error - missing notify emails": {
   213  			params: ActivateIncludeRequest{
   214  				IncludeID: "inc_12345",
   215  				Version:   4,
   216  				Network:   ActivationNetworkStaging,
   217  			},
   218  			withError: ErrStructValidation,
   219  		},
   220  		"validation error - not valid ComplianceRecordNone": {
   221  			params: ActivateIncludeRequest{
   222  				IncludeID:              "inc_12345",
   223  				Version:                4,
   224  				Network:                ActivationNetworkProduction,
   225  				Note:                   "test activation",
   226  				NotifyEmails:           []string{"jbond@example.com"},
   227  				AcknowledgeAllWarnings: true,
   228  				ComplianceRecord: &ComplianceRecordNone{
   229  					UnitTested: true,
   230  					TicketID:   "123",
   231  				},
   232  			},
   233  			withError: ErrStructValidation,
   234  			assertError: func(t *testing.T, err error) {
   235  				assert.Contains(t, err.Error(), "CustomerEmail: cannot be blank")
   236  				assert.Contains(t, err.Error(), "PeerReviewedBy: cannot be blank")
   237  			},
   238  		},
   239  		"validation error - not valid UnitTested field for PRODUCTION activation network and ComplianceRecordNone": {
   240  			params: ActivateIncludeRequest{
   241  				IncludeID:    "inc_12345",
   242  				Version:      4,
   243  				Network:      ActivationNetworkProduction,
   244  				Note:         "test activation",
   245  				NotifyEmails: []string{"jbond@example.com"},
   246  				ComplianceRecord: &ComplianceRecordNone{
   247  					CustomerEmail:  "sb@akamai.com",
   248  					PeerReviewedBy: "sb@akamai.com",
   249  					UnitTested:     false,
   250  					TicketID:       "123",
   251  				},
   252  			},
   253  			withError: ErrStructValidation,
   254  			assertError: func(t *testing.T, err error) {
   255  				assert.Contains(t, err.Error(), "for PRODUCTION activation network and nonComplianceRecord, UnitTested value has to be set to true, otherwise API will not work correctly")
   256  			},
   257  		},
   258  		"validation error - not valid ComplianceRecordOther": {
   259  			params: ActivateIncludeRequest{
   260  				IncludeID:              "inc_12345",
   261  				Version:                4,
   262  				Network:                ActivationNetworkProduction,
   263  				Note:                   "test activation",
   264  				NotifyEmails:           []string{"jbond@example.com"},
   265  				AcknowledgeAllWarnings: true,
   266  				ComplianceRecord:       &ComplianceRecordOther{},
   267  			},
   268  			withError: ErrStructValidation,
   269  			assertError: func(t *testing.T, err error) {
   270  				assert.Contains(t, err.Error(), "OtherNoncomplianceReason: cannot be blank")
   271  			},
   272  		},
   273  	}
   274  	for name, test := range tests {
   275  		t.Run(name, func(t *testing.T) {
   276  			mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   277  				assert.Equal(t, test.expectedPath, r.URL.String())
   278  				assert.Equal(t, http.MethodPost, r.Method)
   279  				w.WriteHeader(test.responseStatus)
   280  				_, err := w.Write([]byte(test.responseBody))
   281  				assert.NoError(t, err)
   282  
   283  				if len(test.expectedRequestBody) > 0 {
   284  					body, err := ioutil.ReadAll(r.Body)
   285  					require.NoError(t, err)
   286  					assert.JSONEq(t, test.expectedRequestBody, string(body))
   287  				}
   288  			}))
   289  			client := mockAPIClient(t, mockServer)
   290  			result, err := client.ActivateInclude(context.Background(), test.params)
   291  
   292  			if test.withError != nil || test.assertError != nil {
   293  				if test.withError != nil {
   294  					assert.True(t, errors.Is(err, test.withError), "want: %s; got: %s", test.withError, err)
   295  				}
   296  				if test.assertError != nil {
   297  					test.assertError(t, err)
   298  				}
   299  				return
   300  			}
   301  
   302  			require.NoError(t, err)
   303  			assert.Equal(t, test.expectedResponse, result)
   304  		})
   305  	}
   306  }
   307  
   308  func TestDeactivateInclude(t *testing.T) {
   309  	tests := map[string]struct {
   310  		params              DeactivateIncludeRequest
   311  		expectedRequestBody string
   312  		responseStatus      int
   313  		responseBody        string
   314  		expectedPath        string
   315  		expectedResponse    *DeactivationIncludeResponse
   316  		withError           error
   317  	}{
   318  		"201 Activate include acknowledging all the warnings": {
   319  			params: DeactivateIncludeRequest{
   320  				IncludeID:              "inc_12345",
   321  				Version:                4,
   322  				Network:                ActivationNetworkStaging,
   323  				Note:                   "test activation",
   324  				NotifyEmails:           []string{"jbond@example.com"},
   325  				AcknowledgeAllWarnings: true,
   326  			},
   327  			expectedRequestBody: `{"acknowledgeAllWarnings":true,"activationType":"DEACTIVATE","ignoreHttpErrors":true,"includeVersion":4,"network":"STAGING","note":"test activation","notifyEmails":["jbond@example.com"]}`,
   328  			expectedPath:        "/papi/v1/includes/inc_12345/activations",
   329  			responseStatus:      http.StatusCreated,
   330  			responseBody: `
   331  {
   332      "activationLink": "/papi/v1/includes/inc_12345/activations/temporary-activation-id"
   333  }`,
   334  			expectedResponse: &DeactivationIncludeResponse{
   335  				ActivationID:   "temporary-activation-id",
   336  				ActivationLink: "/papi/v1/includes/inc_12345/activations/temporary-activation-id",
   337  			},
   338  		},
   339  		"201 Activate include": {
   340  			params: DeactivateIncludeRequest{
   341  				IncludeID:    "inc_12345",
   342  				Version:      4,
   343  				Network:      ActivationNetworkStaging,
   344  				Note:         "test activation",
   345  				NotifyEmails: []string{"jbond@example.com"},
   346  			},
   347  			expectedRequestBody: `{"acknowledgeAllWarnings":false,"activationType":"DEACTIVATE","ignoreHttpErrors":true,"includeVersion":4,"network":"STAGING","note":"test activation","notifyEmails":["jbond@example.com"]}`,
   348  			expectedPath:        "/papi/v1/includes/inc_12345/activations",
   349  			responseStatus:      http.StatusCreated,
   350  			responseBody: `
   351  		{
   352  		   "activationLink": "/papi/v1/includes/inc_12345/activations/temporary-activation-id"
   353  		}`,
   354  			expectedResponse: &DeactivationIncludeResponse{
   355  				ActivationID:   "temporary-activation-id",
   356  				ActivationLink: "/papi/v1/includes/inc_12345/activations/temporary-activation-id",
   357  			},
   358  		},
   359  		"422 Unprocessable entity - deactivate version which is not active on some network": {
   360  			params: DeactivateIncludeRequest{
   361  				IncludeID:              "inc_12345",
   362  				Version:                4,
   363  				Network:                ActivationNetworkProduction,
   364  				Note:                   "test activation",
   365  				NotifyEmails:           []string{"jbond@example.com"},
   366  				AcknowledgeAllWarnings: true,
   367  			},
   368  			expectedPath:   "/papi/v1/includes/inc_12345/activations",
   369  			responseStatus: http.StatusUnprocessableEntity,
   370  			responseBody: `
   371  {
   372      "type": "https://problems.luna.akamaiapis.net/papi/v0/deactivation/include-not-active-in-production",
   373      "title": "Include not active in PRODUCTION",
   374      "detail": "The include cannot be deactivated because it is not active in PRODUCTION.",
   375      "instance": "https://akaa-gcplhccxrheyl6kw-bcfnozqkbaydivqp.luna-dev.akamaiapis.net/papi/v1/includes/inc_12345/activations#12345",
   376      "status": 422
   377  }`,
   378  			withError: &Error{
   379  				Type:       "https://problems.luna.akamaiapis.net/papi/v0/deactivation/include-not-active-in-production",
   380  				Title:      "Include not active in PRODUCTION",
   381  				Detail:     "The include cannot be deactivated because it is not active in PRODUCTION.",
   382  				Instance:   "https://akaa-gcplhccxrheyl6kw-bcfnozqkbaydivqp.luna-dev.akamaiapis.net/papi/v1/includes/inc_12345/activations#12345",
   383  				StatusCode: http.StatusUnprocessableEntity,
   384  			},
   385  		},
   386  		"500 internal server error": {
   387  			params: DeactivateIncludeRequest{
   388  				IncludeID:              "inc_12345",
   389  				Version:                4,
   390  				Network:                ActivationNetworkStaging,
   391  				Note:                   "test activation",
   392  				NotifyEmails:           []string{"jbond@example.com"},
   393  				AcknowledgeAllWarnings: true,
   394  			},
   395  			expectedPath:   "/papi/v1/includes/inc_12345/activations",
   396  			responseStatus: http.StatusInternalServerError,
   397  			responseBody: `
   398  				{
   399  					"type": "internal_error",
   400  				   "title": "Internal Server Error",
   401  				   "detail": "Error getting include",
   402  				   "status": 500
   403  				}`,
   404  			withError: &Error{
   405  				Type:       "internal_error",
   406  				Title:      "Internal Server Error",
   407  				Detail:     "Error getting include",
   408  				StatusCode: http.StatusInternalServerError,
   409  			},
   410  		},
   411  		"validation error - missing include id": {
   412  			params: DeactivateIncludeRequest{
   413  				Version:      4,
   414  				Network:      ActivationNetworkStaging,
   415  				NotifyEmails: []string{"jbond@example.com"},
   416  			},
   417  			withError: ErrStructValidation,
   418  		},
   419  		"validation error - missing version": {
   420  			params: DeactivateIncludeRequest{
   421  				IncludeID:    "inc_12345",
   422  				Network:      ActivationNetworkStaging,
   423  				NotifyEmails: []string{"jbond@example.com"},
   424  			},
   425  			withError: ErrStructValidation,
   426  		},
   427  		"validation error - missing network": {
   428  			params: DeactivateIncludeRequest{
   429  				IncludeID:    "inc_12345",
   430  				Version:      4,
   431  				NotifyEmails: []string{"jbond@example.com"},
   432  			},
   433  			withError: ErrStructValidation,
   434  		},
   435  		"validation error - missing notify emails": {
   436  			params: DeactivateIncludeRequest{
   437  				IncludeID: "inc_12345",
   438  				Version:   4,
   439  				Network:   ActivationNetworkStaging,
   440  			},
   441  			withError: ErrStructValidation,
   442  		},
   443  	}
   444  	for name, test := range tests {
   445  		t.Run(name, func(t *testing.T) {
   446  			mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   447  				assert.Equal(t, test.expectedPath, r.URL.String())
   448  				assert.Equal(t, http.MethodPost, r.Method)
   449  				w.WriteHeader(test.responseStatus)
   450  				_, err := w.Write([]byte(test.responseBody))
   451  				assert.NoError(t, err)
   452  
   453  				if len(test.expectedRequestBody) > 0 {
   454  					body, err := ioutil.ReadAll(r.Body)
   455  					require.NoError(t, err)
   456  					assert.JSONEq(t, test.expectedRequestBody, string(body))
   457  				}
   458  			}))
   459  			client := mockAPIClient(t, mockServer)
   460  			result, err := client.DeactivateInclude(context.Background(), test.params)
   461  			if test.withError != nil {
   462  				assert.True(t, errors.Is(err, test.withError), "want: %s; got: %s", test.withError, err)
   463  				return
   464  			}
   465  			require.NoError(t, err)
   466  			assert.Equal(t, test.expectedResponse, result)
   467  		})
   468  	}
   469  }
   470  
   471  func TestCancelIncludeActivation(t *testing.T) {
   472  	tests := map[string]struct {
   473  		params           CancelIncludeActivationRequest
   474  		responseStatus   int
   475  		responseBody     string
   476  		expectedPath     string
   477  		expectedResponse *CancelIncludeActivationResponse
   478  		withError        error
   479  	}{
   480  		"200 cancel include activation": {
   481  			params: CancelIncludeActivationRequest{
   482  				IncludeID:    "inc_12345",
   483  				ContractID:   "test_contract",
   484  				GroupID:      "test_group",
   485  				ActivationID: "test_activation_123",
   486  			},
   487  			expectedPath:   "/papi/v1/includes/inc_12345/activations/test_activation_123?contractId=test_contract&groupId=test_group",
   488  			responseStatus: http.StatusOK,
   489  			responseBody: `
   490  {
   491      "accountId": "test_account",
   492      "contractId": "test_contract",
   493      "groupId": "test_group",
   494      "activations": {
   495          "items": [
   496              {
   497                  "network": "STAGING",
   498                  "activationType": "ACTIVATE",
   499                  "status": "PENDING_CANCELLATION",
   500                  "submitDate": "2022-12-01T13:18:57Z",
   501                  "updateDate": "2022-12-01T13:19:04Z",
   502                  "note": "test_note_1",
   503                  "notifyEmails": [
   504                      "nomail@nomail.com"
   505                  ],
   506                  "fmaActivationState": "received",
   507                  "includeId": "inc_12345",
   508                  "includeName": "test_include_name",
   509                  "includeVersion": 1,
   510                  "includeActivationId": "test_activation_123"
   511              }
   512          ]
   513      }
   514  }`,
   515  			expectedResponse: &CancelIncludeActivationResponse{
   516  				AccountID:  "test_account",
   517  				ContractID: "test_contract",
   518  				GroupID:    "test_group",
   519  				Activations: IncludeActivationsRes{
   520  					Items: []IncludeActivation{
   521  						{
   522  							Network:             "STAGING",
   523  							ActivationType:      ActivationTypeActivate,
   524  							Status:              ActivationStatusCancelling,
   525  							SubmitDate:          "2022-12-01T13:18:57Z",
   526  							UpdateDate:          "2022-12-01T13:19:04Z",
   527  							Note:                "test_note_1",
   528  							NotifyEmails:        []string{"nomail@nomail.com"},
   529  							FMAActivationState:  "received",
   530  							IncludeID:           "inc_12345",
   531  							IncludeName:         "test_include_name",
   532  							IncludeVersion:      1,
   533  							IncludeActivationID: "test_activation_123",
   534  						},
   535  					},
   536  				},
   537  			},
   538  		},
   539  		"500 internal server error": {
   540  			params: CancelIncludeActivationRequest{
   541  				IncludeID:    "inc_12345",
   542  				ContractID:   "test_contract",
   543  				GroupID:      "test_group",
   544  				ActivationID: "test_activation_123",
   545  			},
   546  			expectedPath:   "/papi/v1/includes/inc_12345/activations/test_activation_123?contractId=test_contract&groupId=test_group",
   547  			responseStatus: http.StatusInternalServerError,
   548  			responseBody: `
   549  				{
   550  					"type": "internal_error",
   551  				   "title": "Internal Server Error",
   552  				   "detail": "Error cancelling include activation",
   553  				   "status": 500
   554  				}`,
   555  			withError: &Error{
   556  				Type:       "internal_error",
   557  				Title:      "Internal Server Error",
   558  				Detail:     "Error cancelling include activation",
   559  				StatusCode: http.StatusInternalServerError,
   560  			},
   561  		},
   562  		"validation error - missing include id": {
   563  			params: CancelIncludeActivationRequest{
   564  				ContractID:   "test_contract",
   565  				GroupID:      "test_group",
   566  				ActivationID: "test_activation_123",
   567  			},
   568  			withError: ErrStructValidation,
   569  		},
   570  		"validation error - contract id": {
   571  			params: CancelIncludeActivationRequest{
   572  				IncludeID:    "inc_12345",
   573  				GroupID:      "test_group",
   574  				ActivationID: "test_activation_123",
   575  			},
   576  			withError: ErrStructValidation,
   577  		},
   578  		"validation error - group id": {
   579  			params: CancelIncludeActivationRequest{
   580  				IncludeID:    "inc_12345",
   581  				ContractID:   "test_contract",
   582  				ActivationID: "test_activation_123",
   583  			},
   584  			withError: ErrStructValidation,
   585  		},
   586  		"validation error - activation id": {
   587  			params: CancelIncludeActivationRequest{
   588  				IncludeID:  "inc_12345",
   589  				ContractID: "test_contract",
   590  				GroupID:    "test_group",
   591  			},
   592  			withError: ErrStructValidation,
   593  		},
   594  	}
   595  	for name, test := range tests {
   596  		t.Run(name, func(t *testing.T) {
   597  			mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   598  				assert.Equal(t, test.expectedPath, r.URL.String())
   599  				assert.Equal(t, http.MethodDelete, r.Method)
   600  				w.WriteHeader(test.responseStatus)
   601  				_, err := w.Write([]byte(test.responseBody))
   602  				assert.NoError(t, err)
   603  			}))
   604  			client := mockAPIClient(t, mockServer)
   605  			result, err := client.CancelIncludeActivation(context.Background(), test.params)
   606  			if test.withError != nil {
   607  				assert.True(t, errors.Is(err, test.withError), "want: %s; got: %s", test.withError, err)
   608  				return
   609  			}
   610  			require.NoError(t, err)
   611  			assert.Equal(t, test.expectedResponse, result)
   612  		})
   613  	}
   614  }
   615  
   616  func TestGetIncludeActivation(t *testing.T) {
   617  	tests := map[string]struct {
   618  		params           GetIncludeActivationRequest
   619  		responseStatus   int
   620  		responseBody     string
   621  		expectedPath     string
   622  		expectedResponse *GetIncludeActivationResponse
   623  		withError        error
   624  	}{
   625  		"200 Get include activation": {
   626  			params: GetIncludeActivationRequest{
   627  				IncludeID:    "inc_12345",
   628  				ActivationID: "atv_12345",
   629  			},
   630  			expectedPath:   "/papi/v1/includes/inc_12345/activations/atv_12345",
   631  			responseStatus: http.StatusOK,
   632  			responseBody: `
   633  {
   634      "accountId": "test_account",
   635      "contractId": "test_contract",
   636      "groupId": "test_group",
   637      "activations": {
   638          "items": [
   639              {
   640                  "activationId": "atv_12345",
   641                  "network": "STAGING",
   642                  "activationType": "ACTIVATE",
   643                  "status": "ACTIVE",
   644                  "submitDate": "2022-10-27T12:27:54Z",
   645                  "updateDate": "2022-10-27T12:28:54Z",
   646                  "note": "DXE test activation",
   647                  "notifyEmails": [
   648                      "test@example.com"
   649                  ],
   650                  "fmaActivationState": "steady",
   651                  "fallbackInfo": {
   652                      "fastFallbackAttempted": false,
   653                      "fallbackVersion": 3,
   654                      "canFastFallback": false,
   655                      "steadyStateTime": 1666873734,
   656                      "fastFallbackExpirationTime": 1666877334,
   657                      "fastFallbackRecoveryState": null
   658                  },
   659                  "includeId": "inc_12345",
   660                  "includeName": "tfp_test1",
   661                  "includeType": "MICROSERVICES",
   662                  "includeVersion": 4
   663              }
   664          ]
   665      }
   666  }`,
   667  			expectedResponse: &GetIncludeActivationResponse{
   668  				AccountID:  "test_account",
   669  				ContractID: "test_contract",
   670  				GroupID:    "test_group",
   671  				Activations: IncludeActivationsRes{
   672  					Items: []IncludeActivation{
   673  						{
   674  							ActivationID:       "atv_12345",
   675  							Network:            "STAGING",
   676  							ActivationType:     ActivationTypeActivate,
   677  							Status:             ActivationStatusActive,
   678  							SubmitDate:         "2022-10-27T12:27:54Z",
   679  							UpdateDate:         "2022-10-27T12:28:54Z",
   680  							Note:               "DXE test activation",
   681  							NotifyEmails:       []string{"test@example.com"},
   682  							FMAActivationState: "steady",
   683  							FallbackInfo: &ActivationFallbackInfo{
   684  								FastFallbackAttempted:      false,
   685  								FallbackVersion:            3,
   686  								CanFastFallback:            false,
   687  								SteadyStateTime:            1666873734,
   688  								FastFallbackExpirationTime: 1666877334,
   689  							},
   690  							IncludeID:      "inc_12345",
   691  							IncludeName:    "tfp_test1",
   692  							IncludeType:    "MICROSERVICES",
   693  							IncludeVersion: 4,
   694  						},
   695  					},
   696  				},
   697  				Activation: IncludeActivation{
   698  					ActivationID:       "atv_12345",
   699  					Network:            "STAGING",
   700  					ActivationType:     ActivationTypeActivate,
   701  					Status:             ActivationStatusActive,
   702  					SubmitDate:         "2022-10-27T12:27:54Z",
   703  					UpdateDate:         "2022-10-27T12:28:54Z",
   704  					Note:               "DXE test activation",
   705  					NotifyEmails:       []string{"test@example.com"},
   706  					FMAActivationState: "steady",
   707  					FallbackInfo: &ActivationFallbackInfo{
   708  						FastFallbackAttempted:      false,
   709  						FallbackVersion:            3,
   710  						CanFastFallback:            false,
   711  						SteadyStateTime:            1666873734,
   712  						FastFallbackExpirationTime: 1666877334,
   713  					},
   714  					IncludeID:      "inc_12345",
   715  					IncludeName:    "tfp_test1",
   716  					IncludeType:    "MICROSERVICES",
   717  					IncludeVersion: 4,
   718  				},
   719  			},
   720  		},
   721  		"200 Get include activation with includeActivationId": {
   722  			params: GetIncludeActivationRequest{
   723  				IncludeID:    "inc_12345",
   724  				ActivationID: "5e597860-1107-461e-8dbe-4e7526e8dd02",
   725  			},
   726  			expectedPath:   "/papi/v1/includes/inc_12345/activations/5e597860-1107-461e-8dbe-4e7526e8dd02",
   727  			responseStatus: http.StatusOK,
   728  			responseBody: `
   729  {
   730      "accountId": "test_account",
   731      "contractId": "test_contract",
   732      "groupId": "test_group",
   733      "activations": {
   734          "items": [
   735              {
   736                  "includeActivationId": "5e597860-1107-461e-8dbe-4e7526e8dd02",
   737                  "network": "STAGING",
   738                  "activationType": "ACTIVATE",
   739                  "status": "ACTIVE",
   740                  "submitDate": "2022-10-27T12:27:54Z",
   741                  "updateDate": "2022-10-27T12:28:54Z",
   742                  "note": "DXE test activation",
   743                  "notifyEmails": [
   744                      "test@example.com"
   745                  ],
   746                  "fmaActivationState": "steady",
   747                  "fallbackInfo": {
   748                      "fastFallbackAttempted": false,
   749                      "fallbackVersion": 3,
   750                      "canFastFallback": false,
   751                      "steadyStateTime": 1666873734,
   752                      "fastFallbackExpirationTime": 1666877334,
   753                      "fastFallbackRecoveryState": null
   754                  },
   755                  "includeId": "inc_12345",
   756                  "includeName": "tfp_test1",
   757                  "includeType": "MICROSERVICES",
   758                  "includeVersion": 4
   759              }
   760          ]
   761      }
   762  }`,
   763  			expectedResponse: &GetIncludeActivationResponse{
   764  				AccountID:  "test_account",
   765  				ContractID: "test_contract",
   766  				GroupID:    "test_group",
   767  				Activations: IncludeActivationsRes{
   768  					Items: []IncludeActivation{
   769  						{
   770  							IncludeActivationID: "5e597860-1107-461e-8dbe-4e7526e8dd02",
   771  							Network:             "STAGING",
   772  							ActivationType:      ActivationTypeActivate,
   773  							Status:              ActivationStatusActive,
   774  							SubmitDate:          "2022-10-27T12:27:54Z",
   775  							UpdateDate:          "2022-10-27T12:28:54Z",
   776  							Note:                "DXE test activation",
   777  							NotifyEmails:        []string{"test@example.com"},
   778  							FMAActivationState:  "steady",
   779  							FallbackInfo: &ActivationFallbackInfo{
   780  								FastFallbackAttempted:      false,
   781  								FallbackVersion:            3,
   782  								CanFastFallback:            false,
   783  								SteadyStateTime:            1666873734,
   784  								FastFallbackExpirationTime: 1666877334,
   785  							},
   786  							IncludeID:      "inc_12345",
   787  							IncludeName:    "tfp_test1",
   788  							IncludeType:    "MICROSERVICES",
   789  							IncludeVersion: 4,
   790  						},
   791  					},
   792  				},
   793  				Activation: IncludeActivation{
   794  					IncludeActivationID: "5e597860-1107-461e-8dbe-4e7526e8dd02",
   795  					Network:             "STAGING",
   796  					ActivationType:      ActivationTypeActivate,
   797  					Status:              ActivationStatusActive,
   798  					SubmitDate:          "2022-10-27T12:27:54Z",
   799  					UpdateDate:          "2022-10-27T12:28:54Z",
   800  					Note:                "DXE test activation",
   801  					NotifyEmails:        []string{"test@example.com"},
   802  					FMAActivationState:  "steady",
   803  					FallbackInfo: &ActivationFallbackInfo{
   804  						FastFallbackAttempted:      false,
   805  						FallbackVersion:            3,
   806  						CanFastFallback:            false,
   807  						SteadyStateTime:            1666873734,
   808  						FastFallbackExpirationTime: 1666877334,
   809  					},
   810  					IncludeID:      "inc_12345",
   811  					IncludeName:    "tfp_test1",
   812  					IncludeType:    "MICROSERVICES",
   813  					IncludeVersion: 4,
   814  				},
   815  			},
   816  		},
   817  		"200 but with activation validation error - ErrMissingComplianceRecord expected": {
   818  			params: GetIncludeActivationRequest{
   819  				IncludeID:    "inc_12345",
   820  				ActivationID: "atv_12345",
   821  			},
   822  			expectedPath:   "/papi/v1/includes/inc_12345/activations/atv_12345",
   823  			responseStatus: http.StatusOK,
   824  			responseBody: `
   825  {
   826      "accountId": "test_account",
   827      "contractId": "test_contract",
   828      "groupId": "test_group",
   829  	"validations": {
   830          "validationSummary": {
   831              "completePercent": 100.0,
   832              "hasValidationError": false,
   833              "hasValidationWarning": false,
   834              "hasSystemError": false,
   835              "hasClientError": true,
   836              "messageState": "HTTP_CLIENT_ERROR",
   837              "errorMessage": "400 : \"{\"type\":\"missing_compliance_record\",\"title\":\"Property Manager Exception\",\"instance\":\"TestInstance\",\"status\":400,\"errors\":[{\"type\":\"missing_compliance_record\",\"title\":\"Property Manager Exception\",\"detail\":\"missing_compliance_record\"}],\"details\":{},\"messageId\":\"missing_compliance_record\",\"params\":[],\"result\":\"ERROR\"}\""
   838          },
   839          "validationErrorsItemList": {
   840              "items": []
   841          },
   842          "network": "PRODUCTION"
   843      },
   844      "activations": {
   845          "items": []
   846      }
   847  }`,
   848  			withError: ErrMissingComplianceRecord,
   849  		},
   850  		"500 internal server error": {
   851  			params: GetIncludeActivationRequest{
   852  				IncludeID:    "inc_12345",
   853  				ActivationID: "atv_12345",
   854  			},
   855  			expectedPath:   "/papi/v1/includes/inc_12345/activations/atv_12345",
   856  			responseStatus: http.StatusInternalServerError,
   857  			responseBody: `
   858  				{
   859  					"type": "internal_error",
   860  				   "title": "Internal Server Error",
   861  				   "detail": "Error getting include",
   862  				   "status": 500
   863  				}`,
   864  			withError: &Error{
   865  				Type:       "internal_error",
   866  				Title:      "Internal Server Error",
   867  				Detail:     "Error getting include",
   868  				StatusCode: http.StatusInternalServerError,
   869  			},
   870  		},
   871  		"validation error - missing include id": {
   872  			params: GetIncludeActivationRequest{
   873  				ActivationID: "atv_12345",
   874  			},
   875  			withError: ErrStructValidation,
   876  		},
   877  		"validation error - activation id": {
   878  			params: GetIncludeActivationRequest{
   879  				IncludeID: "inc_12345",
   880  			},
   881  			withError: ErrStructValidation,
   882  		},
   883  	}
   884  	for name, test := range tests {
   885  		t.Run(name, func(t *testing.T) {
   886  			mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   887  				assert.Equal(t, test.expectedPath, r.URL.String())
   888  				assert.Equal(t, http.MethodGet, r.Method)
   889  				w.WriteHeader(test.responseStatus)
   890  				_, err := w.Write([]byte(test.responseBody))
   891  				assert.NoError(t, err)
   892  			}))
   893  			client := mockAPIClient(t, mockServer)
   894  			result, err := client.GetIncludeActivation(context.Background(), test.params)
   895  			if test.withError != nil {
   896  				assert.True(t, errors.Is(err, test.withError), "want: %s; got: %s", test.withError, err)
   897  				return
   898  			}
   899  			require.NoError(t, err)
   900  			assert.Equal(t, test.expectedResponse, result)
   901  		})
   902  	}
   903  }
   904  
   905  func TestListIncludeActivations(t *testing.T) {
   906  	tests := map[string]struct {
   907  		params           ListIncludeActivationsRequest
   908  		responseStatus   int
   909  		responseBody     string
   910  		expectedPath     string
   911  		expectedResponse *ListIncludeActivationsResponse
   912  		withError        error
   913  	}{
   914  		"200 List include activations": {
   915  			params: ListIncludeActivationsRequest{
   916  				IncludeID:  "inc_12345",
   917  				ContractID: "test_contract",
   918  				GroupID:    "test_group",
   919  			},
   920  			expectedPath:   "/papi/v1/includes/inc_12345/activations?contractId=test_contract&groupId=test_group",
   921  			responseStatus: http.StatusOK,
   922  			responseBody: `
   923  {
   924      "accountId": "test_account",
   925      "contractId": "test_contract",
   926      "groupId": "test_group",
   927      "activations": {
   928          "items": [
   929              {
   930                  "activationId": "atv_12344",
   931                  "network": "STAGING",
   932                  "activationType": "ACTIVATE",
   933                  "status": "ACTIVE",
   934                  "submitDate": "2022-10-27T12:27:54Z",
   935                  "updateDate": "2022-10-27T12:28:54Z",
   936                  "note": "test activation",
   937                  "notifyEmails": [
   938                      "test@example.com"
   939                  ],
   940                  "fmaActivationState": "steady",
   941                  "fallbackInfo": {
   942                      "fastFallbackAttempted": false,
   943                      "fallbackVersion": 3,
   944                      "canFastFallback": false,
   945                      "steadyStateTime": 1666873734,
   946                      "fastFallbackExpirationTime": 1666877334,
   947                      "fastFallbackRecoveryState": null
   948                  },
   949                  "includeId": "inc_12345",
   950                  "includeName": "tfp_test1",
   951                  "includeType": "MICROSERVICES",
   952                  "includeVersion": 4
   953              },
   954              {
   955                  "activationId": "atv_12343",
   956                  "network": "STAGING",
   957                  "activationType": "ACTIVATE",
   958                  "status": "ACTIVE",
   959                  "submitDate": "2022-10-27T11:21:40Z",
   960                  "updateDate": "2022-10-27T11:22:54Z",
   961                  "note": "test activation",
   962                  "notifyEmails": [
   963                      "test@example.com"
   964                  ],
   965                  "fmaActivationState": "steady",
   966                  "fallbackInfo": {
   967                      "fastFallbackAttempted": false,
   968                      "fallbackVersion": 4,
   969                      "canFastFallback": false,
   970                      "steadyStateTime": 1666869774,
   971                      "fastFallbackExpirationTime": 1666873374,
   972                      "fastFallbackRecoveryState": null
   973                  },
   974                  "includeId": "inc_12345",
   975                  "includeName": "tfp_test1",
   976                  "includeType": "MICROSERVICES",
   977                  "includeVersion": 3
   978              },
   979              {
   980                  "activationId": "atv_12343",
   981                  "network": "STAGING",
   982                  "activationType": "DEACTIVATE",
   983                  "status": "ACTIVE",
   984                  "submitDate": "2022-10-26T12:41:58Z",
   985                  "updateDate": "2022-10-26T13:03:04Z",
   986                  "note": "test activation",
   987                  "notifyEmails": [
   988                      "test@example.com"
   989                  ],
   990                  "includeId": "inc_12345",
   991                  "includeName": "tfp_test1",
   992                  "includeType": "MICROSERVICES",
   993                  "includeVersion": 3
   994              },
   995              {
   996                  "activationId": "atv_12342",
   997                  "network": "STAGING",
   998                  "activationType": "ACTIVATE",
   999                  "status": "ACTIVE",
  1000                  "submitDate": "2022-10-26T12:37:49Z",
  1001                  "updateDate": "2022-10-26T12:38:59Z",
  1002                  "note": "test activation",
  1003                  "notifyEmails": [
  1004                      "test@example.com"
  1005                  ],
  1006                  "fmaActivationState": "steady",
  1007                  "fallbackInfo": {
  1008                      "fastFallbackAttempted": false,
  1009                      "fallbackVersion": 4,
  1010                      "canFastFallback": false,
  1011                      "steadyStateTime": 1666787939,
  1012                      "fastFallbackExpirationTime": 1666791539,
  1013                      "fastFallbackRecoveryState": null
  1014                  },
  1015                  "includeId": "inc_12345",
  1016                  "includeName": "tfp_test1",
  1017                  "includeType": "MICROSERVICES",
  1018                  "includeVersion": 2
  1019              },
  1020              {
  1021                  "activationId": "atv_12341",
  1022                  "network": "STAGING",
  1023                  "activationType": "ACTIVATE",
  1024                  "status": "ACTIVE",
  1025                  "submitDate": "2022-08-17T09:13:18Z",
  1026                  "updateDate": "2022-08-17T09:15:35Z",
  1027                  "note": "test activation",
  1028                  "notifyEmails": [
  1029                      "test@example.com"
  1030                  ],
  1031                  "fmaActivationState": "steady",
  1032                  "fallbackInfo": {
  1033                      "fastFallbackAttempted": false,
  1034                      "fallbackVersion": 4,
  1035                      "canFastFallback": false,
  1036                      "steadyStateTime": 1660727735,
  1037                      "fastFallbackExpirationTime": 1660731335,
  1038                      "fastFallbackRecoveryState": null
  1039                  },
  1040                  "includeId": "inc_12345",
  1041                  "includeName": "tfp_test1",
  1042                  "includeType": "MICROSERVICES",
  1043                  "includeVersion": 1
  1044              }
  1045          ]
  1046      }
  1047  }`,
  1048  			expectedResponse: &ListIncludeActivationsResponse{
  1049  				AccountID:  "test_account",
  1050  				ContractID: "test_contract",
  1051  				GroupID:    "test_group",
  1052  				Activations: IncludeActivationsRes{
  1053  					Items: []IncludeActivation{
  1054  						{
  1055  							ActivationID:       "atv_12344",
  1056  							Network:            "STAGING",
  1057  							ActivationType:     ActivationTypeActivate,
  1058  							Status:             ActivationStatusActive,
  1059  							SubmitDate:         "2022-10-27T12:27:54Z",
  1060  							UpdateDate:         "2022-10-27T12:28:54Z",
  1061  							Note:               "test activation",
  1062  							NotifyEmails:       []string{"test@example.com"},
  1063  							FMAActivationState: "steady",
  1064  							FallbackInfo: &ActivationFallbackInfo{
  1065  								FastFallbackAttempted:      false,
  1066  								FallbackVersion:            3,
  1067  								CanFastFallback:            false,
  1068  								SteadyStateTime:            1666873734,
  1069  								FastFallbackExpirationTime: 1666877334,
  1070  							},
  1071  							IncludeID:      "inc_12345",
  1072  							IncludeName:    "tfp_test1",
  1073  							IncludeType:    "MICROSERVICES",
  1074  							IncludeVersion: 4,
  1075  						},
  1076  						{
  1077  							ActivationID:       "atv_12343",
  1078  							Network:            "STAGING",
  1079  							ActivationType:     ActivationTypeActivate,
  1080  							Status:             ActivationStatusActive,
  1081  							SubmitDate:         "2022-10-27T11:21:40Z",
  1082  							UpdateDate:         "2022-10-27T11:22:54Z",
  1083  							Note:               "test activation",
  1084  							NotifyEmails:       []string{"test@example.com"},
  1085  							FMAActivationState: "steady",
  1086  							FallbackInfo: &ActivationFallbackInfo{
  1087  								FastFallbackAttempted:      false,
  1088  								FallbackVersion:            4,
  1089  								CanFastFallback:            false,
  1090  								SteadyStateTime:            1666869774,
  1091  								FastFallbackExpirationTime: 1666873374,
  1092  							},
  1093  							IncludeID:      "inc_12345",
  1094  							IncludeName:    "tfp_test1",
  1095  							IncludeType:    "MICROSERVICES",
  1096  							IncludeVersion: 3,
  1097  						},
  1098  						{
  1099  							ActivationID:   "atv_12343",
  1100  							Network:        "STAGING",
  1101  							ActivationType: ActivationTypeDeactivate,
  1102  							Status:         ActivationStatusActive,
  1103  							SubmitDate:     "2022-10-26T12:41:58Z",
  1104  							UpdateDate:     "2022-10-26T13:03:04Z",
  1105  							Note:           "test activation",
  1106  							NotifyEmails:   []string{"test@example.com"},
  1107  							IncludeID:      "inc_12345",
  1108  							IncludeName:    "tfp_test1",
  1109  							IncludeType:    "MICROSERVICES",
  1110  							IncludeVersion: 3,
  1111  						},
  1112  						{
  1113  							ActivationID:       "atv_12342",
  1114  							Network:            "STAGING",
  1115  							ActivationType:     ActivationTypeActivate,
  1116  							Status:             ActivationStatusActive,
  1117  							SubmitDate:         "2022-10-26T12:37:49Z",
  1118  							UpdateDate:         "2022-10-26T12:38:59Z",
  1119  							Note:               "test activation",
  1120  							NotifyEmails:       []string{"test@example.com"},
  1121  							FMAActivationState: "steady",
  1122  							FallbackInfo: &ActivationFallbackInfo{
  1123  								FastFallbackAttempted:      false,
  1124  								FallbackVersion:            4,
  1125  								CanFastFallback:            false,
  1126  								SteadyStateTime:            1666787939,
  1127  								FastFallbackExpirationTime: 1666791539,
  1128  							},
  1129  							IncludeID:      "inc_12345",
  1130  							IncludeName:    "tfp_test1",
  1131  							IncludeType:    "MICROSERVICES",
  1132  							IncludeVersion: 2,
  1133  						},
  1134  						{
  1135  							ActivationID:       "atv_12341",
  1136  							Network:            "STAGING",
  1137  							ActivationType:     ActivationTypeActivate,
  1138  							Status:             ActivationStatusActive,
  1139  							SubmitDate:         "2022-08-17T09:13:18Z",
  1140  							UpdateDate:         "2022-08-17T09:15:35Z",
  1141  							Note:               "test activation",
  1142  							NotifyEmails:       []string{"test@example.com"},
  1143  							FMAActivationState: "steady",
  1144  							FallbackInfo: &ActivationFallbackInfo{
  1145  								FastFallbackAttempted:      false,
  1146  								FallbackVersion:            4,
  1147  								CanFastFallback:            false,
  1148  								SteadyStateTime:            1660727735,
  1149  								FastFallbackExpirationTime: 1660731335,
  1150  							},
  1151  							IncludeID:      "inc_12345",
  1152  							IncludeName:    "tfp_test1",
  1153  							IncludeType:    "MICROSERVICES",
  1154  							IncludeVersion: 1,
  1155  						},
  1156  					},
  1157  				},
  1158  			},
  1159  		},
  1160  		"500 internal server error": {
  1161  			params: ListIncludeActivationsRequest{
  1162  				IncludeID:  "inc_12345",
  1163  				ContractID: "test_contract",
  1164  				GroupID:    "test_group",
  1165  			},
  1166  			expectedPath:   "/papi/v1/includes/inc_12345/activations?contractId=test_contract&groupId=test_group",
  1167  			responseStatus: http.StatusInternalServerError,
  1168  			responseBody: `
  1169  				{
  1170  					"type": "internal_error",
  1171  				   "title": "Internal Server Error",
  1172  				   "detail": "Error getting include",
  1173  				   "status": 500
  1174  				}`,
  1175  			withError: &Error{
  1176  				Type:       "internal_error",
  1177  				Title:      "Internal Server Error",
  1178  				Detail:     "Error getting include",
  1179  				StatusCode: http.StatusInternalServerError,
  1180  			},
  1181  		},
  1182  		"validation error - missing include id": {
  1183  			params: ListIncludeActivationsRequest{
  1184  				ContractID: "test_contract",
  1185  				GroupID:    "test_group",
  1186  			},
  1187  			withError: ErrStructValidation,
  1188  		},
  1189  		"validation error - contract id": {
  1190  			params: ListIncludeActivationsRequest{
  1191  				IncludeID: "inc_12345",
  1192  				GroupID:   "test_group",
  1193  			},
  1194  			withError: ErrStructValidation,
  1195  		},
  1196  		"validation error - group id": {
  1197  			params: ListIncludeActivationsRequest{
  1198  				IncludeID:  "inc_12345",
  1199  				ContractID: "test_contract",
  1200  			},
  1201  			withError: ErrStructValidation,
  1202  		},
  1203  	}
  1204  	for name, test := range tests {
  1205  		t.Run(name, func(t *testing.T) {
  1206  			mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  1207  				assert.Equal(t, test.expectedPath, r.URL.String())
  1208  				assert.Equal(t, http.MethodGet, r.Method)
  1209  				w.WriteHeader(test.responseStatus)
  1210  				_, err := w.Write([]byte(test.responseBody))
  1211  				assert.NoError(t, err)
  1212  			}))
  1213  			client := mockAPIClient(t, mockServer)
  1214  			result, err := client.ListIncludeActivations(context.Background(), test.params)
  1215  			if test.withError != nil {
  1216  				assert.True(t, errors.Is(err, test.withError), "want: %s; got: %s", test.withError, err)
  1217  				return
  1218  			}
  1219  			require.NoError(t, err)
  1220  			assert.Equal(t, test.expectedResponse, result)
  1221  		})
  1222  	}
  1223  }
  1224  
  1225  func TestExtractError(t *testing.T) {
  1226  	tests := map[string]struct {
  1227  		errorMessage string
  1228  		wantedError  *ActivationError
  1229  	}{
  1230  		"all data": {
  1231  			errorMessage: "111 : \"{\"type\":\"type1\",\"title\":\"title1\",\"instance\":\"instance1\",\"status\":404,\"errors\":[{\"type\":\"type2\",\"title\":\"title2\",\"detail\":\"detail1\"}],\"details\":{},\"messageId\":\"message1\",\"params\":[],\"result\":\"result1\"}\"",
  1232  			wantedError: &ActivationError{
  1233  				Type:     "type1",
  1234  				Title:    "title1",
  1235  				Instance: "instance1",
  1236  				Status:   404,
  1237  				Errors: []ActivationErrorMessage{
  1238  					{
  1239  						Type:   "type2",
  1240  						Title:  "title2",
  1241  						Detail: "detail1",
  1242  					},
  1243  				},
  1244  				MessageID: "message1",
  1245  				Result:    "result1",
  1246  			},
  1247  		},
  1248  		"minimum data": {
  1249  			errorMessage: "111 : \"{\"type\":\"type1\",\"title\":\"title1\",\"instance\":\"instance1\",\"status\":404,\"errors\":[{\"type\":\"type2\",\"title\":\"title2\",\"detail\":\"detail1\"}],\"messageId\":\"message1\",\"result\":\"result1\"}\"",
  1250  			wantedError: &ActivationError{
  1251  				Type:     "type1",
  1252  				Title:    "title1",
  1253  				Instance: "instance1",
  1254  				Status:   404,
  1255  				Errors: []ActivationErrorMessage{
  1256  					{
  1257  						Type:   "type2",
  1258  						Title:  "title2",
  1259  						Detail: "detail1",
  1260  					},
  1261  				},
  1262  				MessageID: "message1",
  1263  				Result:    "result1",
  1264  			},
  1265  		},
  1266  	}
  1267  
  1268  	for name, test := range tests {
  1269  		t.Run(name, func(t *testing.T) {
  1270  			gotErr := extractError(test.errorMessage)
  1271  			assert.EqualError(t, test.wantedError, gotErr.Error())
  1272  		})
  1273  	}
  1274  }