Repository: ctreminiom/go-atlassian
Pull request #116 (2022-05-09 22:07:35)

:sparkles: Added the ability to change the filter owner.
1. Added the ability to change the filter owner.
2. https://developer.atlassian.com/cloud/jira/platform/rest/v3/api-group-filters/#api-rest-api-3-filter-id-owner-put


Patch:
diff --git a/jira/v2/filter.go b/jira/v2/filter.go
index ea682a0..a6391ad 100644
--- a/jira/v2/filter.go
+++ b/jira/v2/filter.go
@@ -233,3 +233,40 @@ func (f *FilterService) Delete(ctx context.Context, filterID int) (response *Res
 
 	return
 }
+
+// Change changes the owner of the filter.
+// Docs: https://docs.go-atlassian.io/jira-software-cloud/filters#change-filter-owner
+func (f *FilterService) Change(ctx context.Context, filterID int, accountID string) (response *ResponseScheme, err error) {
+
+	if filterID == 0 {
+		return nil, models.ErrNoFilterIDError
+	}
+
+	if accountID == "" {
+		return nil, models.ErrNoAccountIDError
+	}
+
+	payload := struct {
+		AccountID string `json:"accountId"`
+	}{
+		AccountID: accountID,
+	}
+
+	payloadAsReader, _ := transformStructToReader(&payload)
+	endpoint := fmt.Sprintf("rest/api/2/filter/%v/owner", filterID)
+
+	request, err := f.client.newRequest(ctx, http.MethodPut, endpoint, payloadAsReader)
+	if err != nil {
+		return
+	}
+
+	request.Header.Set("Accept", "application/json")
+	request.Header.Set("Content-Type", "application/json")
+
+	response, err = f.client.call(request, nil)
+	if err != nil {
+		return
+	}
+
+	return
+}
diff --git a/jira/v3/filter.go b/jira/v3/filter.go
index 9a0ded0..c40cfd4 100644
--- a/jira/v3/filter.go
+++ b/jira/v3/filter.go
@@ -240,3 +240,40 @@ func (f *FilterService) Delete(ctx context.Context, filterID int) (response *Res
 
 	return
 }
+
+// Change changes the owner of the filter.
+// Docs: https://docs.go-atlassian.io/jira-software-cloud/filters#change-filter-owner
+func (f *FilterService) Change(ctx context.Context, filterID int, accountID string) (response *ResponseScheme, err error) {
+
+	if filterID == 0 {
+		return nil, models.ErrNoFilterIDError
+	}
+
+	if accountID == "" {
+		return nil, models.ErrNoAccountIDError
+	}
+
+	payload := struct {
+		AccountID string `json:"accountId"`
+	}{
+		AccountID: accountID,
+	}
+
+	payloadAsReader, _ := transformStructToReader(&payload)
+	endpoint := fmt.Sprintf("rest/api/3/filter/%v/owner", filterID)
+
+	request, err := f.client.newRequest(ctx, http.MethodPut, endpoint, payloadAsReader)
+	if err != nil {
+		return
+	}
+
+	request.Header.Set("Accept", "application/json")
+	request.Header.Set("Content-Type", "application/json")
+
+	response, err = f.client.call(request, nil)
+	if err != nil {
+		return
+	}
+
+	return
+}


Test patch:
diff --git a/jira/v2/filter_test.go b/jira/v2/filter_test.go
index 13cc081..06deb3f 100644
--- a/jira/v2/filter_test.go
+++ b/jira/v2/filter_test.go
@@ -1253,3 +1253,144 @@ func TestFilterService_Update_V2(t *testing.T) {
 		})
 	}
 }
+
+func TestFilterService_Change(t *testing.T) {
+
+	testCases := []struct {
+		name               string
+		filterID           int
+		accountID          string
+		mockFile           string
+		wantHTTPMethod     string
+		endpoint           string
+		context            context.Context
+		wantHTTPCodeReturn int
+		wantErr            bool
+		expectedError      string
+	}{
+		{
+			name:               "when the parameters are correct",
+			filterID:           102222,
+			accountID:          "b91d9257-0a87-410d-9dbd-2d2b3878fbe4",
+			wantHTTPMethod:     http.MethodPut,
+			endpoint:           "/rest/api/2/filter/102222/owner",
+			context:            context.Background(),
+			wantHTTPCodeReturn: http.StatusNoContent,
+			wantErr:            false,
+		},
+
+		{
+			name:               "when the response code is invalid",
+			filterID:           102222,
+			accountID:          "b91d9257-0a87-410d-9dbd-2d2b3878fbe4",
+			wantHTTPMethod:     http.MethodPut,
+			endpoint:           "/rest/api/2/filter/102222/owner",
+			context:            context.Background(),
+			wantHTTPCodeReturn: http.StatusBadRequest,
+			wantErr:            true,
+			expectedError:      "request failed. Please analyze the request body for more details. Status Code: 400",
+		},
+
+		{
+			name:               "when the context is not provided",
+			filterID:           102222,
+			accountID:          "b91d9257-0a87-410d-9dbd-2d2b3878fbe4",
+			wantHTTPMethod:     http.MethodPut,
+			endpoint:           "/rest/api/2/filter/102222/owner",
+			context:            nil,
+			wantHTTPCodeReturn: http.StatusNoContent,
+			wantErr:            true,
+			expectedError:      "request creation failed: net/http: nil Context",
+		},
+
+		{
+			name:               "when the account id is not provided",
+			filterID:           102222,
+			accountID:          "",
+			wantHTTPMethod:     http.MethodPut,
+			endpoint:           "/rest/api/2/filter/102222/owner",
+			context:            context.Background(),
+			wantHTTPCodeReturn: http.StatusNoContent,
+			wantErr:            true,
+			expectedError:      "jira: no account id set",
+		},
+
+		{
+			name:               "when the filter id is not provided",
+			filterID:           0,
+			accountID:          "b91d9257-0a87-410d-9dbd-2d2b3878fbe4",
+			wantHTTPMethod:     http.MethodPut,
+			endpoint:           "/rest/api/2/filter/102222/owner",
+			context:            context.Background(),
+			wantHTTPCodeReturn: http.StatusNoContent,
+			wantErr:            true,
+			expectedError:      "agile: no filter id set",
+		},
+	}
+
+	for _, testCase := range testCases {
+
+		t.Run(testCase.name, func(t *testing.T) {
+
+			//Init a new HTTP mock server
+			mockOptions := mockServerOptions{
+				Endpoint:           testCase.endpoint,
+				MockFilePath:       testCase.mockFile,
+				MethodAccepted:     testCase.wantHTTPMethod,
+				ResponseCodeWanted: testCase.wantHTTPCodeReturn,
+			}
+
+			mockServer, err := startMockServer(&mockOptions)
+			if err != nil {
+				t.Fatal(err)
+			}
+
+			defer mockServer.Close()
+
+			//Init the library instance
+			mockClient, err := startMockClient(mockServer.URL)
+			if err != nil {
+				t.Fatal(err)
+			}
+
+			i := &FilterService{client: mockClient}
+
+			gotResponse, err := i.Change(testCase.context, testCase.filterID, testCase.accountID)
+
+			if testCase.wantErr {
+
+				if err != nil {
+					t.Logf("error returned: %v", err.Error())
+				}
+
+				assert.EqualError(t, err, testCase.expectedError)
+
+				if gotResponse != nil {
+					t.Logf("HTTP Code Wanted: %v, HTTP Code Returned: %v", testCase.wantHTTPCodeReturn, gotResponse.Code)
+				}
+			} else {
+
+				assert.NoError(t, err)
+				assert.NotEqual(t, gotResponse, nil)
+
+				apiEndpoint, err := url.Parse(gotResponse.Endpoint)
+				if err != nil {
+					t.Fatal(err)
+				}
+
+				var endpointToAssert string
+
+				if apiEndpoint.Query().Encode() != "" {
+					endpointToAssert = fmt.Sprintf("%v?%v", apiEndpoint.Path, apiEndpoint.Query().Encode())
+				} else {
+					endpointToAssert = apiEndpoint.Path
+				}
+
+				t.Logf("HTTP Endpoint Wanted: %v, HTTP Endpoint Returned: %v", testCase.endpoint, endpointToAssert)
+				assert.Equal(t, testCase.endpoint, endpointToAssert)
+			}
+		})
+
+	}
+
+}
diff --git a/jira/v3/filter_test.go b/jira/v3/filter_test.go
index c9e8a0c..82316c3 100644
--- a/jira/v3/filter_test.go
+++ b/jira/v3/filter_test.go
@@ -1253,3 +1253,144 @@ func TestFilterService_Update(t *testing.T) {
 		})
 	}
 }
+
+func TestFilterService_Change(t *testing.T) {
+
+	testCases := []struct {
+		name               string
+		filterID           int
+		accountID          string
+		mockFile           string
+		wantHTTPMethod     string
+		endpoint           string
+		context            context.Context
+		wantHTTPCodeReturn int
+		wantErr            bool
+		expectedError      string
+	}{
+		{
+			name:               "when the parameters are correct",
+			filterID:           102222,
+			accountID:          "b91d9257-0a87-410d-9dbd-2d2b3878fbe4",
+			wantHTTPMethod:     http.MethodPut,
+			endpoint:           "/rest/api/3/filter/102222/owner",
+			context:            context.Background(),
+			wantHTTPCodeReturn: http.StatusNoContent,
+			wantErr:            false,
+		},
+
+		{
+			name:               "when the response code is invalid",
+			filterID:           102222,
+			accountID:          "b91d9257-0a87-410d-9dbd-2d2b3878fbe4",
+			wantHTTPMethod:     http.MethodPut,
+			endpoint:           "/rest/api/3/filter/102222/owner",
+			context:            context.Background(),
+			wantHTTPCodeReturn: http.StatusBadRequest,
+			wantErr:            true,
+			expectedError:      "request failed. Please analyze the request body for more details. Status Code: 400",
+		},
+
+		{
+			name:               "when the context is not provided",
+			filterID:           102222,
+			accountID:          "b91d9257-0a87-410d-9dbd-2d2b3878fbe4",
+			wantHTTPMethod:     http.MethodPut,
+			endpoint:           "/rest/api/3/filter/102222/owner",
+			context:            nil,
+			wantHTTPCodeReturn: http.StatusNoContent,
+			wantErr:            true,
+			expectedError:      "request creation failed: net/http: nil Context",
+		},
+
+		{
+			name:               "when the account id is not provided",
+			filterID:           102222,
+			accountID:          "",
+			wantHTTPMethod:     http.MethodPut,
+			endpoint:           "/rest/api/3/filter/102222/owner",
+			context:            context.Background(),
+			wantHTTPCodeReturn: http.StatusNoContent,
+			wantErr:            true,
+			expectedError:      "jira: no account id set",
+		},
+
+		{
+			name:               "when the filter id is not provided",
+			filterID:           0,
+			accountID:          "b91d9257-0a87-410d-9dbd-2d2b3878fbe4",
+			wantHTTPMethod:     http.MethodPut,
+			endpoint:           "/rest/api/3/filter/102222/owner",
+			context:            context.Background(),
+			wantHTTPCodeReturn: http.StatusNoContent,
+			wantErr:            true,
+			expectedError:      "agile: no filter id set",
+		},
+	}
+
+	for _, testCase := range testCases {
+
+		t.Run(testCase.name, func(t *testing.T) {
+
+			//Init a new HTTP mock server
+			mockOptions := mockServerOptions{
+				Endpoint:           testCase.endpoint,
+				MockFilePath:       testCase.mockFile,
+				MethodAccepted:     testCase.wantHTTPMethod,
+				ResponseCodeWanted: testCase.wantHTTPCodeReturn,
+			}
+
+			mockServer, err := startMockServer(&mockOptions)
+			if err != nil {
+				t.Fatal(err)
+			}
+
+			defer mockServer.Close()
+
+			//Init the library instance
+			mockClient, err := startMockClient(mockServer.URL)
+			if err != nil {
+				t.Fatal(err)
+			}
+
+			i := &FilterService{client: mockClient}
+
+			gotResponse, err := i.Change(testCase.context, testCase.filterID, testCase.accountID)
+
+			if testCase.wantErr {
+
+				if err != nil {
+					t.Logf("error returned: %v", err.Error())
+				}
+
+				assert.EqualError(t, err, testCase.expectedError)
+
+				if gotResponse != nil {
+					t.Logf("HTTP Code Wanted: %v, HTTP Code Returned: %v", testCase.wantHTTPCodeReturn, gotResponse.Code)
+				}
+			} else {
+
+				assert.NoError(t, err)
+				assert.NotEqual(t, gotResponse, nil)
+
+				apiEndpoint, err := url.Parse(gotResponse.Endpoint)
+				if err != nil {
+					t.Fatal(err)
+				}
+
+				var endpointToAssert string
+
+				if apiEndpoint.Query().Encode() != "" {
+					endpointToAssert = fmt.Sprintf("%v?%v", apiEndpoint.Path, apiEndpoint.Query().Encode())
+				} else {
+					endpointToAssert = apiEndpoint.Path
+				}
+
+				t.Logf("HTTP Endpoint Wanted: %v, HTTP Endpoint Returned: %v", testCase.endpoint, endpointToAssert)
+				assert.Equal(t, testCase.endpoint, endpointToAssert)
+			}
+		})
+
+	}
+
+}