github.com/akamai/AkamaiOPEN-edgegrid-golang/v8@v8.1.0/pkg/cloudlets/v3/policy_activation_test.go (about)

     1  package v3
     2  
     3  import (
     4  	"context"
     5  	"encoding/json"
     6  	"io"
     7  	"net/http"
     8  	"net/http/httptest"
     9  	"testing"
    10  	"time"
    11  
    12  	"github.com/stretchr/testify/assert"
    13  	"github.com/stretchr/testify/require"
    14  )
    15  
    16  func TestListPolicyActivations(t *testing.T) {
    17  	t.Parallel()
    18  
    19  	var policyID int64 = 1234
    20  
    21  	tests := map[string]struct {
    22  		params           ListPolicyActivationsRequest
    23  		responseStatus   int
    24  		responseBody     string
    25  		expectedPath     string
    26  		expectedResponse *PolicyActivations
    27  		withError        bool
    28  		assertError      func(*testing.T, error)
    29  	}{
    30  		"200 OK": {
    31  			params: ListPolicyActivationsRequest{
    32  				PolicyID: policyID,
    33  			},
    34  			responseStatus: http.StatusOK,
    35  			expectedPath:   "/cloudlets/v3/policies/1234/activations",
    36  			expectedResponse: &PolicyActivations{
    37  				PolicyActivations: []PolicyActivation{
    38  					{
    39  						CreatedBy:   "testUser",
    40  						CreatedDate: *newTimeFromString(t, "2023-10-25T10:33:47.982Z"),
    41  						FinishDate:  nil,
    42  						ID:          234,
    43  						Links: []Link{
    44  							{
    45  								Href: "/cloudlets/v3/policies/1234/activations/234",
    46  								Rel:  "self",
    47  							},
    48  						},
    49  						Network:              StagingNetwork,
    50  						Operation:            OperationDeactivation,
    51  						PolicyID:             policyID,
    52  						PolicyVersion:        1,
    53  						PolicyVersionDeleted: false,
    54  						Status:               ActivationStatusInProgress,
    55  					},
    56  					{
    57  						CreatedBy:   "testUser",
    58  						CreatedDate: *newTimeFromString(t, "2023-10-23T11:21:19.896Z"),
    59  						FinishDate:  newTimeFromString(t, "2023-10-23T11:22:57.589Z"),
    60  						ID:          123,
    61  						Links: []Link{
    62  							{
    63  								Href: "/cloudlets/v3/policies/1234/activations/123",
    64  								Rel:  "self",
    65  							},
    66  						},
    67  						Network:              StagingNetwork,
    68  						Operation:            OperationActivation,
    69  						PolicyID:             policyID,
    70  						PolicyVersion:        1,
    71  						PolicyVersionDeleted: false,
    72  						Status:               ActivationStatusSuccess,
    73  					},
    74  				},
    75  				Links: []Link{
    76  					{
    77  						Href: "/cloudlets/v3/policies/1234/activations?page=0&size=1000",
    78  						Rel:  "self",
    79  					},
    80  				},
    81  				Page: Page{
    82  					Number:        0,
    83  					Size:          1000,
    84  					TotalElements: 2,
    85  					TotalPages:    1,
    86  				},
    87  			},
    88  			responseBody: `
    89  {
    90  	"content": [
    91  		{
    92  			"createdBy": "testUser",
    93  			"createdDate": "2023-10-25T10:33:47.982Z",
    94  			"finishDate": null,
    95  			"id": 234,
    96  			"links": [
    97  				{
    98  					"href": "/cloudlets/v3/policies/1234/activations/234",
    99  					"rel": "self"
   100  				}
   101  			],
   102  			"network": "STAGING",
   103  			"operation": "DEACTIVATION",
   104  			"policyId": 1234,
   105  			"policyVersion": 1,
   106  			"policyVersionDeleted": false,
   107  			"status": "IN_PROGRESS"
   108  		},
   109  		{
   110  			"createdBy": "testUser",
   111  			"createdDate": "2023-10-23T11:21:19.896Z",
   112  			"finishDate": "2023-10-23T11:22:57.589Z",
   113  			"id": 123,
   114  			"links": [
   115  				{
   116  					"href": "/cloudlets/v3/policies/1234/activations/123",
   117  					"rel": "self"
   118  				}
   119  			],
   120  			"network": "STAGING",
   121  			"operation": "ACTIVATION",
   122  			"policyId": 1234,
   123  			"policyVersion": 1,
   124  			"policyVersionDeleted": false,
   125  			"status": "SUCCESS"
   126  		}
   127  	],
   128  	"links": [
   129  		{
   130  			"href": "/cloudlets/v3/policies/1234/activations?page=0&size=1000",
   131  			"rel": "self"
   132  		}
   133  	],
   134  	"page": {
   135  		"number": 0,
   136  		"size": 1000,
   137  		"totalElements": 2,
   138  		"totalPages": 1
   139  	}
   140  }`,
   141  		},
   142  		"200 OK with query": {
   143  			params: ListPolicyActivationsRequest{
   144  				PolicyID: policyID,
   145  				Page:     1,
   146  				Size:     10,
   147  			},
   148  			responseStatus: http.StatusOK,
   149  			expectedPath:   "/cloudlets/v3/policies/1234/activations?page=1&size=10",
   150  			expectedResponse: &PolicyActivations{
   151  				PolicyActivations: []PolicyActivation{},
   152  				Links: []Link{
   153  					{
   154  						Href: "/cloudlets/v3/policies/1234/activations?page=0&size=10",
   155  						Rel:  "first",
   156  					},
   157  					{
   158  						Href: "/cloudlets/v3/policies/1234/activations?page=0&size=10",
   159  						Rel:  "prev",
   160  					},
   161  					{
   162  						Href: "/cloudlets/v3/policies/1234/activations?page=1&size=10",
   163  						Rel:  "self",
   164  					},
   165  					{
   166  						Href: "/cloudlets/v3/policies/1234/activations?page=0&size=10",
   167  						Rel:  "last",
   168  					},
   169  				},
   170  				Page: Page{
   171  					Number:        1,
   172  					Size:          10,
   173  					TotalElements: 2,
   174  					TotalPages:    1,
   175  				},
   176  			},
   177  			responseBody: `
   178  {
   179  	"content": [],
   180  	"links": [
   181  		{
   182  			"href": "/cloudlets/v3/policies/1234/activations?page=0&size=10",
   183  			"rel": "first"
   184  		},
   185  		{
   186  			"href": "/cloudlets/v3/policies/1234/activations?page=0&size=10",
   187  			"rel": "prev"
   188  		},
   189  		{
   190  			"href": "/cloudlets/v3/policies/1234/activations?page=1&size=10",
   191  			"rel": "self"
   192  		},
   193  		{
   194  			"href": "/cloudlets/v3/policies/1234/activations?page=0&size=10",
   195  			"rel": "last"
   196  		}
   197  	],
   198  	"page": {
   199  		"number": 1,
   200  		"size": 10,
   201  		"totalElements": 2,
   202  		"totalPages": 1
   203  	}
   204  }`,
   205  		},
   206  		"500 Internal Server Error": {
   207  			params: ListPolicyActivationsRequest{
   208  				PolicyID: policyID,
   209  			},
   210  			responseStatus: http.StatusInternalServerError,
   211  			expectedPath:   "/cloudlets/v3/policies/1234/activations",
   212  			responseBody: `
   213  {
   214  	"type": "internal_error",
   215  	"title": "Internal Server Error",
   216  	"status": 500,
   217  	"requestId": "1",
   218  	"requestTime": "12:00",
   219  	"clientIp": "1.1.1.1",
   220  	"serverIp": "2.2.2.2",
   221  	"method": "GET"
   222  }`,
   223  			withError: true,
   224  			assertError: func(t *testing.T, err error) {
   225  				want := &Error{
   226  					Type:        "internal_error",
   227  					Title:       "Internal Server Error",
   228  					Status:      http.StatusInternalServerError,
   229  					RequestID:   "1",
   230  					RequestTime: "12:00",
   231  					ClientIP:    "1.1.1.1",
   232  					ServerIP:    "2.2.2.2",
   233  					Method:      "GET",
   234  				}
   235  				assert.ErrorIs(t, err, want)
   236  			},
   237  		},
   238  		"request validation failed": {
   239  			params: ListPolicyActivationsRequest{
   240  				Page: -1,
   241  				Size: 5,
   242  			},
   243  			withError: true,
   244  			assertError: func(t *testing.T, err error) {
   245  				assert.ErrorContains(t, err, "Page: must be no less than 0")
   246  				assert.ErrorContains(t, err, "PolicyID: cannot be blank")
   247  				assert.ErrorContains(t, err, "Size: must be no less than 10")
   248  			},
   249  		},
   250  	}
   251  
   252  	for name, tc := range tests {
   253  		name, tc := name, tc
   254  		t.Run(name, func(t *testing.T) {
   255  			t.Parallel()
   256  
   257  			mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   258  				assert.Equal(t, tc.expectedPath, r.URL.String())
   259  				assert.Equal(t, http.MethodGet, r.Method)
   260  				w.WriteHeader(tc.responseStatus)
   261  				_, err := w.Write([]byte(tc.responseBody))
   262  				assert.NoError(t, err)
   263  			}))
   264  			client := mockAPIClient(t, mockServer)
   265  			result, err := client.ListPolicyActivations(context.Background(), tc.params)
   266  
   267  			if tc.withError {
   268  				tc.assertError(t, err)
   269  				return
   270  			}
   271  			require.NoError(t, err)
   272  			assert.Equal(t, tc.expectedResponse, result)
   273  		})
   274  	}
   275  }
   276  
   277  func TestActivatePolicy(t *testing.T) {
   278  	t.Parallel()
   279  
   280  	var policyID int64 = 1234
   281  
   282  	tests := map[string]struct {
   283  		params           ActivatePolicyRequest
   284  		responseStatus   int
   285  		responseBody     string
   286  		expectedPath     string
   287  		expectedReqBody  string
   288  		expectedResponse *PolicyActivation
   289  		withError        bool
   290  		assertError      func(*testing.T, error)
   291  	}{
   292  		"202 Accepted": {
   293  			params: ActivatePolicyRequest{
   294  				PolicyID:      policyID,
   295  				Network:       StagingNetwork,
   296  				PolicyVersion: 1,
   297  			},
   298  			responseStatus: http.StatusAccepted,
   299  			expectedPath:   "/cloudlets/v3/policies/1234/activations",
   300  			expectedResponse: &PolicyActivation{
   301  				CreatedBy:   "testUser",
   302  				CreatedDate: *newTimeFromString(t, "2023-10-25T10:33:47.982Z"),
   303  				FinishDate:  nil,
   304  				ID:          123,
   305  				Links: []Link{
   306  					{
   307  						Href: "/cloudlets/v3/policies/1234/activations/123",
   308  						Rel:  "self",
   309  					},
   310  				},
   311  				Network:              StagingNetwork,
   312  				Operation:            OperationActivation,
   313  				PolicyID:             policyID,
   314  				PolicyVersion:        1,
   315  				PolicyVersionDeleted: false,
   316  				Status:               ActivationStatusInProgress,
   317  			},
   318  			expectedReqBody: `
   319  {
   320  	"network": "STAGING",
   321  	"policyVersion": 1,
   322  	"operation": "ACTIVATION"
   323  }`,
   324  			responseBody: `
   325  {
   326  	"createdBy": "testUser",
   327  	"createdDate": "2023-10-25T10:33:47.982Z",
   328  	"finishDate": null,
   329  	"id": 123,
   330  	"links": [
   331  		{
   332  			"href": "/cloudlets/v3/policies/1234/activations/123",
   333  			"rel": "self"
   334  		}
   335  	],
   336  	"network": "STAGING",
   337  	"operation": "ACTIVATION",
   338  	"policyId": 1234,
   339  	"policyVersion": 1,
   340  	"policyVersionDeleted": false,
   341  	"status": "IN_PROGRESS"
   342  }`,
   343  		},
   344  		"500 Internal Server Error": {
   345  			params: ActivatePolicyRequest{
   346  				PolicyID:      policyID,
   347  				Network:       StagingNetwork,
   348  				PolicyVersion: 1,
   349  			},
   350  			responseStatus: http.StatusInternalServerError,
   351  			expectedPath:   "/cloudlets/v3/policies/1234/activations",
   352  			expectedReqBody: `
   353  {
   354  	"network": "STAGING",
   355  	"policyVersion": 1,
   356  	"operation": "ACTIVATION"
   357  }`,
   358  			responseBody: `
   359  {
   360  	"type": "internal_error",
   361  	"title": "Internal Server Error",
   362  	"status": 500,
   363  	"requestId": "1",
   364  	"requestTime": "12:00",
   365  	"clientIp": "1.1.1.1",
   366  	"serverIp": "2.2.2.2",
   367  	"method": "GET"
   368  }`,
   369  			withError: true,
   370  			assertError: func(t *testing.T, err error) {
   371  				want := &Error{
   372  					Type:        "internal_error",
   373  					Title:       "Internal Server Error",
   374  					Status:      http.StatusInternalServerError,
   375  					RequestID:   "1",
   376  					RequestTime: "12:00",
   377  					ClientIP:    "1.1.1.1",
   378  					ServerIP:    "2.2.2.2",
   379  					Method:      "GET",
   380  				}
   381  				assert.ErrorIs(t, err, want)
   382  			},
   383  		},
   384  		"request validation failed": {
   385  			params:    ActivatePolicyRequest{},
   386  			withError: true,
   387  			assertError: func(t *testing.T, err error) {
   388  				assert.ErrorContains(t, err, "PolicyID: cannot be blank")
   389  				assert.ErrorContains(t, err, "PolicyVersion: cannot be blank")
   390  				assert.ErrorContains(t, err, "Network: cannot be blank")
   391  			},
   392  		},
   393  	}
   394  
   395  	for name, tc := range tests {
   396  		name, tc := name, tc
   397  		t.Run(name, func(t *testing.T) {
   398  			t.Parallel()
   399  
   400  			mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   401  				assert.Equal(t, tc.expectedPath, r.URL.String())
   402  				assert.Equal(t, http.MethodPost, r.Method)
   403  				w.WriteHeader(tc.responseStatus)
   404  				_, err := w.Write([]byte(tc.responseBody))
   405  				assert.NoError(t, err)
   406  				if tc.expectedReqBody != "" {
   407  					body, err := io.ReadAll(r.Body)
   408  					assert.NoError(t, err)
   409  					assert.JSONEq(t, tc.expectedReqBody, string(body))
   410  				}
   411  			}))
   412  			client := mockAPIClient(t, mockServer)
   413  			result, err := client.ActivatePolicy(context.Background(), tc.params)
   414  
   415  			if tc.withError {
   416  				tc.assertError(t, err)
   417  				return
   418  			}
   419  			require.NoError(t, err)
   420  			assert.Equal(t, tc.expectedResponse, result)
   421  		})
   422  	}
   423  }
   424  
   425  func TestDeactivatePolicy(t *testing.T) {
   426  	t.Parallel()
   427  
   428  	var policyID int64 = 1234
   429  
   430  	tests := map[string]struct {
   431  		params           DeactivatePolicyRequest
   432  		responseStatus   int
   433  		responseBody     string
   434  		expectedPath     string
   435  		expectedReqBody  string
   436  		expectedResponse *PolicyActivation
   437  		withError        bool
   438  		assertError      func(*testing.T, error)
   439  	}{
   440  		"202 Accepted": {
   441  			params: DeactivatePolicyRequest{
   442  				PolicyID:      policyID,
   443  				Network:       StagingNetwork,
   444  				PolicyVersion: 1,
   445  			},
   446  			responseStatus: http.StatusAccepted,
   447  			expectedPath:   "/cloudlets/v3/policies/1234/activations",
   448  			expectedResponse: &PolicyActivation{
   449  				CreatedBy:   "testUser",
   450  				CreatedDate: *newTimeFromString(t, "2023-10-25T10:33:47.982Z"),
   451  				FinishDate:  nil,
   452  				ID:          123,
   453  				Links: []Link{
   454  					{
   455  						Href: "/cloudlets/v3/policies/1234/activations/123",
   456  						Rel:  "self",
   457  					},
   458  				},
   459  				Network:              StagingNetwork,
   460  				Operation:            OperationDeactivation,
   461  				PolicyID:             policyID,
   462  				PolicyVersion:        1,
   463  				PolicyVersionDeleted: false,
   464  				Status:               ActivationStatusInProgress,
   465  			},
   466  			expectedReqBody: `
   467  {
   468  	"network": "STAGING",
   469  	"policyVersion": 1,
   470  	"operation": "DEACTIVATION"
   471  }`,
   472  			responseBody: `
   473  {
   474  	"createdBy": "testUser",
   475  	"createdDate": "2023-10-25T10:33:47.982Z",
   476  	"finishDate": null,
   477  	"id": 123,
   478  	"links": [
   479  		{
   480  			"href": "/cloudlets/v3/policies/1234/activations/123",
   481  			"rel": "self"
   482  		}
   483  	],
   484  	"network": "STAGING",
   485  	"operation": "DEACTIVATION",
   486  	"policyId": 1234,
   487  	"policyVersion": 1,
   488  	"policyVersionDeleted": false,
   489  	"status": "IN_PROGRESS"
   490  }`,
   491  		},
   492  		"500 Internal Server Error": {
   493  			params: DeactivatePolicyRequest{
   494  				PolicyID:      policyID,
   495  				Network:       ProductionNetwork,
   496  				PolicyVersion: 1,
   497  			},
   498  			responseStatus: http.StatusInternalServerError,
   499  			expectedPath:   "/cloudlets/v3/policies/1234/activations",
   500  			expectedReqBody: `
   501  {
   502  	"network": "PRODUCTION",
   503  	"policyVersion": 1,
   504  	"operation": "DEACTIVATION"
   505  }`,
   506  			responseBody: `
   507  {
   508  	"type": "internal_error",
   509  	"title": "Internal Server Error",
   510  	"status": 500,
   511  	"requestId": "1",
   512  	"requestTime": "12:00",
   513  	"clientIp": "1.1.1.1",
   514  	"serverIp": "2.2.2.2",
   515  	"method": "GET"
   516  }`,
   517  			withError: true,
   518  			assertError: func(t *testing.T, err error) {
   519  				want := &Error{
   520  					Type:        "internal_error",
   521  					Title:       "Internal Server Error",
   522  					Status:      http.StatusInternalServerError,
   523  					RequestID:   "1",
   524  					RequestTime: "12:00",
   525  					ClientIP:    "1.1.1.1",
   526  					ServerIP:    "2.2.2.2",
   527  					Method:      "GET",
   528  				}
   529  				assert.ErrorIs(t, err, want)
   530  			},
   531  		},
   532  		"request validation failed": {
   533  			params: DeactivatePolicyRequest{
   534  				Network: "OTHER",
   535  			},
   536  			withError: true,
   537  			assertError: func(t *testing.T, err error) {
   538  				assert.ErrorContains(t, err, "PolicyID: cannot be blank")
   539  				assert.ErrorContains(t, err, "PolicyVersion: cannot be blank")
   540  				assert.ErrorContains(t, err, "Network: value 'OTHER' is invalid. Must be one of: 'STAGING' or 'PRODUCTION'")
   541  			},
   542  		},
   543  	}
   544  
   545  	for name, tc := range tests {
   546  		name, tc := name, tc
   547  		t.Run(name, func(t *testing.T) {
   548  			t.Parallel()
   549  
   550  			mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   551  				assert.Equal(t, tc.expectedPath, r.URL.String())
   552  				assert.Equal(t, http.MethodPost, r.Method)
   553  				w.WriteHeader(tc.responseStatus)
   554  				_, err := w.Write([]byte(tc.responseBody))
   555  				assert.NoError(t, err)
   556  				if tc.expectedReqBody != "" {
   557  					body, err := io.ReadAll(r.Body)
   558  					assert.NoError(t, err)
   559  					assert.JSONEq(t, tc.expectedReqBody, string(body))
   560  				}
   561  			}))
   562  			client := mockAPIClient(t, mockServer)
   563  			result, err := client.DeactivatePolicy(context.Background(), tc.params)
   564  
   565  			if tc.withError {
   566  				tc.assertError(t, err)
   567  				return
   568  			}
   569  			require.NoError(t, err)
   570  			assert.Equal(t, tc.expectedResponse, result)
   571  		})
   572  	}
   573  }
   574  
   575  func TestGetPolicyActivation(t *testing.T) {
   576  	t.Parallel()
   577  
   578  	var policyID int64 = 1234
   579  	var activationID int64 = 123
   580  
   581  	tests := map[string]struct {
   582  		params           GetPolicyActivationRequest
   583  		responseStatus   int
   584  		responseBody     string
   585  		expectedPath     string
   586  		expectedResponse *PolicyActivation
   587  		withError        bool
   588  		assertError      func(*testing.T, error)
   589  	}{
   590  		"200 OK": {
   591  			params: GetPolicyActivationRequest{
   592  				PolicyID:     policyID,
   593  				ActivationID: activationID,
   594  			},
   595  			responseStatus: http.StatusOK,
   596  			expectedPath:   "/cloudlets/v3/policies/1234/activations/123",
   597  			expectedResponse: &PolicyActivation{
   598  				CreatedBy:   "testUser",
   599  				CreatedDate: *newTimeFromString(t, "2023-10-23T11:21:19.896Z"),
   600  				FinishDate:  newTimeFromString(t, "2023-10-23T11:22:57.589Z"),
   601  				ID:          activationID,
   602  				Links: []Link{
   603  					{
   604  						Href: "/cloudlets/v3/policies/1234/activations/123",
   605  						Rel:  "self",
   606  					},
   607  				},
   608  				Network:              StagingNetwork,
   609  				Operation:            OperationActivation,
   610  				PolicyID:             policyID,
   611  				PolicyVersion:        1,
   612  				PolicyVersionDeleted: false,
   613  				Status:               ActivationStatusSuccess,
   614  			},
   615  			responseBody: `
   616  {
   617  	"createdBy": "testUser",
   618  	"createdDate": "2023-10-23T11:21:19.896Z",
   619  	"finishDate": "2023-10-23T11:22:57.589Z",
   620  	"id": 123,
   621  	"links": [
   622  		{
   623  			"href": "/cloudlets/v3/policies/1234/activations/123",
   624  			"rel": "self"
   625  		}
   626  	],
   627  	"network": "STAGING",
   628  	"operation": "ACTIVATION",
   629  	"policyId": 1234,
   630  	"policyVersion": 1,
   631  	"policyVersionDeleted": false,
   632  	"status": "SUCCESS"
   633  }`,
   634  		},
   635  		"404 Not Found": {
   636  			params: GetPolicyActivationRequest{
   637  				PolicyID:     policyID,
   638  				ActivationID: 1,
   639  			},
   640  			responseStatus: http.StatusNotFound,
   641  			expectedPath:   "/cloudlets/v3/policies/1234/activations/1",
   642  			responseBody: `
   643  {
   644  	"instance": "testInstance",
   645  	"status": 404,
   646  	"title": "Not found",
   647  	"type": "/cloudlets/v3/error-types/not-found",
   648  	"errors": [
   649  		{
   650  			"detail": "Activation with id '1' not found.",
   651  			"title": "Not found"
   652  		}
   653  	]
   654  }`,
   655  			withError: true,
   656  			assertError: func(t *testing.T, err error) {
   657  				want := &Error{
   658  					Type:     "/cloudlets/v3/error-types/not-found",
   659  					Title:    "Not found",
   660  					Status:   http.StatusNotFound,
   661  					Instance: "testInstance",
   662  					Errors:   json.RawMessage(`[{"detail": "Activation with id '1' not found.", "title": "Not found"}]`),
   663  				}
   664  				assert.ErrorIs(t, err, want)
   665  			},
   666  		},
   667  		"500 Internal Server Error": {
   668  			params: GetPolicyActivationRequest{
   669  				PolicyID:     policyID,
   670  				ActivationID: activationID,
   671  			},
   672  			responseStatus: http.StatusInternalServerError,
   673  			expectedPath:   "/cloudlets/v3/policies/1234/activations/123",
   674  			responseBody: `
   675  {
   676  	"type": "internal_error",
   677  	"title": "Internal Server Error",
   678  	"status": 500,
   679  	"requestId": "1",
   680  	"requestTime": "12:00",
   681  	"clientIp": "1.1.1.1",
   682  	"serverIp": "2.2.2.2",
   683  	"method": "GET"
   684  }`,
   685  			withError: true,
   686  			assertError: func(t *testing.T, err error) {
   687  				want := &Error{
   688  					Type:        "internal_error",
   689  					Title:       "Internal Server Error",
   690  					Status:      http.StatusInternalServerError,
   691  					RequestID:   "1",
   692  					RequestTime: "12:00",
   693  					ClientIP:    "1.1.1.1",
   694  					ServerIP:    "2.2.2.2",
   695  					Method:      "GET",
   696  				}
   697  				assert.ErrorIs(t, err, want)
   698  			},
   699  		},
   700  		"request validation failed": {
   701  			params:    GetPolicyActivationRequest{},
   702  			withError: true,
   703  			assertError: func(t *testing.T, err error) {
   704  				assert.ErrorContains(t, err, "PolicyID: cannot be blank")
   705  				assert.ErrorContains(t, err, "ActivationID: cannot be blank")
   706  			},
   707  		},
   708  	}
   709  
   710  	for name, tc := range tests {
   711  		name, tc := name, tc
   712  		t.Run(name, func(t *testing.T) {
   713  			t.Parallel()
   714  
   715  			mockServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   716  				assert.Equal(t, tc.expectedPath, r.URL.String())
   717  				assert.Equal(t, http.MethodGet, r.Method)
   718  				w.WriteHeader(tc.responseStatus)
   719  				_, err := w.Write([]byte(tc.responseBody))
   720  				assert.NoError(t, err)
   721  			}))
   722  			client := mockAPIClient(t, mockServer)
   723  			result, err := client.GetPolicyActivation(context.Background(), tc.params)
   724  
   725  			if tc.withError {
   726  				tc.assertError(t, err)
   727  				return
   728  			}
   729  			require.NoError(t, err)
   730  			assert.Equal(t, tc.expectedResponse, result)
   731  		})
   732  	}
   733  }
   734  
   735  func newTimeFromString(t *testing.T, s string) *time.Time {
   736  	parsedTime, err := time.Parse(time.RFC3339Nano, s)
   737  	require.NoError(t, err)
   738  	return &parsedTime
   739  }