Repository: ctreminiom/go-atlassian
Pull request #94 (2021-12-05 20:48:15)

:sparkles: Added the Move screen tab field method


Patch:
diff --git a/.codecov.yml b/.codecov.yml
deleted file mode 100644
index 5bdb509..0000000
--- a/.codecov.yml
+++ /dev/null
@@ -1,18 +0,0 @@
-coverage:
-  range: 80..100
-  round: down
-  precisi.on: 2
-
-  status:
-    project:                   # measuring the overall project coverage
-      default:                 # context, you can create multiple ones with custom titles
-        enabled: yes           # must be yes|true to enable this status
-        target: 90             # specify the target coverage for each commit status
-          #   option: "auto" (must increase from parent commit or pull request base)
-        #   option: "X%" a static target percentage to hit
-        threshold: null        # allowed to drop X% and still result in a "success" commit status
-        if_not_found: success  # if parent is not found report status as success, error, or failure
-        if_ci_failed: error    # if ci fails report status as success, error, or failure
-    patch:
-      default:
-        enabled: no
\ No newline at end of file
diff --git a/codecov.yml b/codecov.yml
index 52dd98c..e412bfe 100644
--- a/codecov.yml
+++ b/codecov.yml
@@ -1,3 +1,22 @@
+coverage:
+  range: 80..100
+  round: down
+  precisi.on: 2
+
+  status:
+    project:                   # measuring the overall project coverage
+      default:                 # context, you can create multiple ones with custom titles
+        enabled: yes           # must be yes|true to enable this status
+        target: 90             # specify the target coverage for each commit status
+        #   option: "auto" (must increase from parent commit or pull request base)
+        #   option: "X%" a static target percentage to hit
+        threshold: null        # allowed to drop X% and still result in a "success" commit status
+        if_not_found: success  # if parent is not found report status as success, error, or failure
+        if_ci_failed: error    # if ci fails report status as success, error, or failure
+    patch:
+      default:
+        enabled: no
+=======
 # Team Yaml
 coverage:
   round: down
diff --git a/jira/v2/screenTabField.go b/jira/v2/screenTabField.go
index 8f51a77..e956d4a 100644
--- a/jira/v2/screenTabField.go
+++ b/jira/v2/screenTabField.go
@@ -91,3 +91,42 @@ func (s *ScreenTabFieldService) Remove(ctx context.Context, screenID, tabID int,
 
 	return
 }
+
+// Move moves a screen tab field.
+func (s *ScreenTabFieldService) Move(ctx context.Context, screenID, tabID int, fieldID, after, position string) (response *ResponseScheme,
+	err error) {
+
+	if screenID == 0 {
+		return nil, models.ErrNoScreenIDError
+	}
+
+	if len(fieldID) == 0 {
+		return nil, models.ErrNoFieldIDError
+	}
+
+	payload := struct {
+		After    string `json:"after,omitempty"`
+		Position string `json:"position,omitempty"`
+	}{
+		After:    after,
+		Position: position,
+	}
+
+	payloadAsReader, _ := transformStructToReader(&payload)
+	var endpoint = fmt.Sprintf("rest/api/2/screens/%v/tabs/%v/fields/%v/move", screenID, tabID, fieldID)
+
+	request, err := s.client.newRequest(ctx, http.MethodPost, endpoint, payloadAsReader)
+	if err != nil {
+		return
+	}
+
+	request.Header.Set("Accept", "application/json")
+	request.Header.Set("Content-Type", "application/json")
+
+	response, err = s.client.call(request, nil)
+	if err != nil {
+		return
+	}
+
+	return
+}
diff --git a/jira/v3/screenTabField.go b/jira/v3/screenTabField.go
index d8238f2..5771cee 100644
--- a/jira/v3/screenTabField.go
+++ b/jira/v3/screenTabField.go
@@ -91,3 +91,42 @@ func (s *ScreenTabFieldService) Remove(ctx context.Context, screenID, tabID int,
 
 	return
 }
+
+// Move moves a screen tab field.
+func (s *ScreenTabFieldService) Move(ctx context.Context, screenID, tabID int, fieldID, after, position string) (response *ResponseScheme,
+	err error) {
+
+	if screenID == 0 {
+		return nil, models.ErrNoScreenIDError
+	}
+
+	if len(fieldID) == 0 {
+		return nil, models.ErrNoFieldIDError
+	}
+
+	payload := struct {
+		After    string `json:"after,omitempty"`
+		Position string `json:"position,omitempty"`
+	}{
+		After:    after,
+		Position: position,
+	}
+
+	payloadAsReader, _ := transformStructToReader(&payload)
+	var endpoint = fmt.Sprintf("rest/api/3/screens/%v/tabs/%v/fields/%v/move", screenID, tabID, fieldID)
+
+	request, err := s.client.newRequest(ctx, http.MethodPost, endpoint, payloadAsReader)
+	if err != nil {
+		return
+	}
+
+	request.Header.Set("Accept", "application/json")
+	request.Header.Set("Content-Type", "application/json")
+
+	response, err = s.client.call(request, nil)
+	if err != nil {
+		return
+	}
+
+	return
+}
diff --git a/pkg/infra/models/errors.go b/pkg/infra/models/errors.go
index 775bc25..6545db8 100644
--- a/pkg/infra/models/errors.go
+++ b/pkg/infra/models/errors.go
@@ -81,4 +81,6 @@ var (
 	ErrNoProjectKeySliceError         = errors.New("jira: no project key's set")
 	ErrNoWorkflowIDError              = errors.New("jira: no workflow id set")
 	ErrNoWorkflowSchemeIDError        = errors.New("jira: no workflow scheme id set")
+	ErrNoScreenIDError                = errors.New("jira: no screen id set")
+	ErrNoScreenTabIDError             = errors.New("jira: no screen tab id set")
 )


Test patch:
diff --git a/jira/v2/screenTabField_test.go b/jira/v2/screenTabField_test.go
index 00db178..90f63bd 100644
--- a/jira/v2/screenTabField_test.go
+++ b/jira/v2/screenTabField_test.go
@@ -450,3 +450,167 @@ func TestScreenTabFieldService_Remove(t *testing.T) {
 	}
 
 }
+
+func TestScreenTabFieldService_Move(t *testing.T) {
+
+	testCases := []struct {
+		name               string
+		screenID           int
+		tabID              int
+		fieldID            string
+		after              string
+		position           string
+		mockFile           string
+		wantHTTPMethod     string
+		endpoint           string
+		context            context.Context
+		wantHTTPCodeReturn int
+		wantErr            bool
+	}{
+		{
+			name:               "MoveFieldFromScreenTabWhenTheParamsAreCorrect",
+			screenID:           10001,
+			tabID:              12,
+			fieldID:            "1000",
+			after:              "",
+			position:           "First",
+			wantHTTPMethod:     http.MethodPost,
+			endpoint:           "/rest/api/2/screens/10001/tabs/12/fields/1000/move",
+			context:            context.Background(),
+			wantHTTPCodeReturn: http.StatusNoContent,
+			wantErr:            false,
+		},
+
+		{
+			name:               "MoveFieldFromScreenTabWhenTheScreenIDIsNotProvided",
+			screenID:           0,
+			tabID:              12,
+			fieldID:            "1000",
+			after:              "",
+			position:           "First",
+			wantHTTPMethod:     http.MethodPost,
+			endpoint:           "/rest/api/2/screens/10001/tabs/12/fields/1000/move",
+			context:            context.Background(),
+			wantHTTPCodeReturn: http.StatusNoContent,
+			wantErr:            true,
+		},
+
+		{
+			name:               "MoveFieldFromScreenTabWhenTheFieldIDIsNotProvided",
+			screenID:           10001,
+			tabID:              12,
+			fieldID:            "",
+			after:              "",
+			position:           "First",
+			wantHTTPMethod:     http.MethodPost,
+			endpoint:           "/rest/api/2/screens/10001/tabs/12/fields/1000/move",
+			context:            context.Background(),
+			wantHTTPCodeReturn: http.StatusNoContent,
+			wantErr:            true,
+		},
+
+		{
+			name:               "MoveFieldFromScreenTabWhenTheRequestMethodIsIncorrect",
+			screenID:           10001,
+			tabID:              12,
+			fieldID:            "1000",
+			after:              "",
+			position:           "First",
+			wantHTTPMethod:     http.MethodHead,
+			endpoint:           "/rest/api/2/screens/10001/tabs/12/fields/1000/move",
+			context:            context.Background(),
+			wantHTTPCodeReturn: http.StatusNoContent,
+			wantErr:            true,
+		},
+
+		{
+			name:               "MoveFieldFromScreenTabWhenTheStatusCodeIsIncorrect",
+			screenID:           10001,
+			tabID:              12,
+			fieldID:            "1000",
+			after:              "",
+			position:           "First",
+			wantHTTPMethod:     http.MethodPost,
+			endpoint:           "/rest/api/2/screens/10001/tabs/12/fields/1000/move",
+			context:            context.Background(),
+			wantHTTPCodeReturn: http.StatusBadRequest,
+			wantErr:            true,
+		},
+
+		{
+			name:               "MoveFieldFromScreenTabWhenTheContextIsNotProvided",
+			screenID:           10001,
+			tabID:              12,
+			fieldID:            "1000",
+			after:              "",
+			position:           "First",
+			wantHTTPMethod:     http.MethodPost,
+			endpoint:           "/rest/api/2/screens/10001/tabs/12/fields/1000/move",
+			context:            nil,
+			wantHTTPCodeReturn: http.StatusNoContent,
+			wantErr:            true,
+		},
+	}
+
+	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 := &ScreenTabFieldService{client: mockClient}
+
+			gotResponse, err := i.Move(testCase.context, testCase.screenID, testCase.tabID, testCase.fieldID, testCase.after, testCase.position)
+
+			if testCase.wantErr {
+
+				if err != nil {
+					t.Logf("error returned: %v", err.Error())
+				}
+
+				assert.Error(t, err)
+			} 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/screenTabField_test.go b/jira/v3/screenTabField_test.go
index 1104dc2..2165143 100644
--- a/jira/v3/screenTabField_test.go
+++ b/jira/v3/screenTabField_test.go
@@ -475,3 +475,167 @@ func TestScreenTabFieldService_Remove(t *testing.T) {
 	}
 
 }
+
+func TestScreenTabFieldService_Move(t *testing.T) {
+
+	testCases := []struct {
+		name               string
+		screenID           int
+		tabID              int
+		fieldID            string
+		after              string
+		position           string
+		mockFile           string
+		wantHTTPMethod     string
+		endpoint           string
+		context            context.Context
+		wantHTTPCodeReturn int
+		wantErr            bool
+	}{
+		{
+			name:               "MoveFieldFromScreenTabWhenTheParamsAreCorrect",
+			screenID:           10001,
+			tabID:              12,
+			fieldID:            "1000",
+			after:              "",
+			position:           "First",
+			wantHTTPMethod:     http.MethodPost,
+			endpoint:           "/rest/api/3/screens/10001/tabs/12/fields/1000/move",
+			context:            context.Background(),
+			wantHTTPCodeReturn: http.StatusNoContent,
+			wantErr:            false,
+		},
+
+		{
+			name:               "MoveFieldFromScreenTabWhenTheScreenIDIsNotProvided",
+			screenID:           0,
+			tabID:              12,
+			fieldID:            "1000",
+			after:              "",
+			position:           "First",
+			wantHTTPMethod:     http.MethodPost,
+			endpoint:           "/rest/api/3/screens/10001/tabs/12/fields/1000/move",
+			context:            context.Background(),
+			wantHTTPCodeReturn: http.StatusNoContent,
+			wantErr:            true,
+		},
+
+		{
+			name:               "MoveFieldFromScreenTabWhenTheFieldIDIsNotProvided",
+			screenID:           10001,
+			tabID:              12,
+			fieldID:            "",
+			after:              "",
+			position:           "First",
+			wantHTTPMethod:     http.MethodPost,
+			endpoint:           "/rest/api/3/screens/10001/tabs/12/fields/1000/move",
+			context:            context.Background(),
+			wantHTTPCodeReturn: http.StatusNoContent,
+			wantErr:            true,
+		},
+
+		{
+			name:               "MoveFieldFromScreenTabWhenTheRequestMethodIsIncorrect",
+			screenID:           10001,
+			tabID:              12,
+			fieldID:            "1000",
+			after:              "",
+			position:           "First",
+			wantHTTPMethod:     http.MethodHead,
+			endpoint:           "/rest/api/3/screens/10001/tabs/12/fields/1000/move",
+			context:            context.Background(),
+			wantHTTPCodeReturn: http.StatusNoContent,
+			wantErr:            true,
+		},
+
+		{
+			name:               "MoveFieldFromScreenTabWhenTheStatusCodeIsIncorrect",
+			screenID:           10001,
+			tabID:              12,
+			fieldID:            "1000",
+			after:              "",
+			position:           "First",
+			wantHTTPMethod:     http.MethodPost,
+			endpoint:           "/rest/api/3/screens/10001/tabs/12/fields/1000/move",
+			context:            context.Background(),
+			wantHTTPCodeReturn: http.StatusBadRequest,
+			wantErr:            true,
+		},
+
+		{
+			name:               "MoveFieldFromScreenTabWhenTheContextIsNotProvided",
+			screenID:           10001,
+			tabID:              12,
+			fieldID:            "1000",
+			after:              "",
+			position:           "First",
+			wantHTTPMethod:     http.MethodPost,
+			endpoint:           "/rest/api/3/screens/10001/tabs/12/fields/1000/move",
+			context:            nil,
+			wantHTTPCodeReturn: http.StatusNoContent,
+			wantErr:            true,
+		},
+	}
+
+	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 := &ScreenTabFieldService{client: mockClient}
+
+			gotResponse, err := i.Move(testCase.context, testCase.screenID, testCase.tabID, testCase.fieldID, testCase.after, testCase.position)
+
+			if testCase.wantErr {
+
+				if err != nil {
+					t.Logf("error returned: %v", err.Error())
+				}
+
+				assert.Error(t, err)
+			} 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)
+			}
+		})
+
+	}
+
+}