From 9d775d7dbb8c600111c7a0b7cafc910cc0d1bcf6 Mon Sep 17 00:00:00 2001 From: Wytse Vellema Date: Fri, 16 Jun 2023 18:05:24 +0200 Subject: [PATCH] Adds support for servicedeskapi request comments --- cloud/servicedesk.go | 104 ++++++++++++++++++++++++++++++++++++++ cloud/servicedesk_test.go | 102 +++++++++++++++++++++++++++++++++++++ 2 files changed, 206 insertions(+) diff --git a/cloud/servicedesk.go b/cloud/servicedesk.go index dac54f7a..f007c9dc 100644 --- a/cloud/servicedesk.go +++ b/cloud/servicedesk.go @@ -6,6 +6,8 @@ import ( "fmt" "io" "net/http" + "net/url" + "strconv" "github.com/google/go-querystring/query" ) @@ -209,3 +211,105 @@ func (s *ServiceDeskService) ListCustomers(ctx context.Context, serviceDeskID in return customerList, resp, nil } + +// ListComments lists comments for a ServiceDesk issue. +// +// https://docs.atlassian.com/jira-servicedesk/REST/3.6.2/#servicedeskapi/request/{issueIdOrKey}/comment-getRequestComments +func (s *ServiceDeskService) ListComments(ctx context.Context, issueKeyOrID string, params ServiceDeskCommentsListParams) (*ServiceDeskCommentsList, *Response, error) { + apiEndPoint := fmt.Sprintf("rest/servicedeskapi/request/%s/comment", issueKeyOrID) + + req, err := s.client.NewRequest(ctx, http.MethodGet, apiEndPoint, nil) + req.Header.Set("Accept", "application/json") + + query := url.Values{} + query.Add("start", strconv.Itoa(params.Start)) + query.Add("limit", strconv.Itoa(params.Limit)) + + if params.HidePublic { + query.Add("public", "false") + } else { + query.Add("public", "true") + } + + if params.HideInternal { + query.Add("internal", "false") + } else { + query.Add("internal", "true") + } + + // Add parameters to url + req.URL.RawQuery = query.Encode() + + if err != nil { + return nil, nil, err + } + + orgs := new(ServiceDeskCommentsList) + resp, err := s.client.Do(req, &orgs) + if err != nil { + jerr := NewJiraError(resp, err) + return nil, resp, jerr + } + defer resp.Body.Close() + + return orgs, resp, nil +} + +type ServiceDeskCommentsListParams struct { + // Specifies whether to hide public comments or not. Default: false. + HidePublic bool + // Specifies whether to hide internal comments or not. Default: false. + HideInternal bool + // The starting index of the returned comments. Base index: 0. See the Pagination(https://docs.atlassian.com/jira-servicedesk/REST/3.6.2/#pagination) section for more details. + Start int + // The maximum number of comments to return per page. Default: 50. See the Pagination(https://docs.atlassian.com/jira-servicedesk/REST/3.6.2/#pagination) section for more details. + Limit int +} + +type ServiceDeskComment struct { + ID string `json:"id"` + Body string `json:"body"` + Public bool `json:"public"` + Author struct { + Name string `json:"name"` + Key string `json:"key"` + EmailAddress string `json:"emailAddress"` + DisplayName string `json:"displayName"` + Active bool `json:"active"` + TimeZone string `json:"timeZone"` + Links struct { + JiraRest string `json:"jiraRest"` + AvatarUrls struct { + Four8X48 string `json:"48x48"` + Two4X24 string `json:"24x24"` + One6X16 string `json:"16x16"` + Three2X32 string `json:"32x32"` + } `json:"avatarUrls"` + Self string `json:"self"` + } `json:"_links"` + } `json:"author"` + Created struct { + Iso8601 string `json:"iso8601"` + Jira string `json:"jira"` + Friendly string `json:"friendly"` + EpochMillis int64 `json:"epochMillis"` + } `json:"created"` + Links struct { + Self string `json:"self"` + } `json:"_links"` +} + +type ServiceDeskCommentsList struct { + Expands []interface{} `json:"_expands"` + Size int `json:"size"` + Start int `json:"start"` + Limit int `json:"limit"` + IsLastPage bool `json:"isLastPage"` + Links struct { + Base string `json:"base"` + Context string `json:"context"` + Next string `json:"next"` + Prev string `json:"prev"` + } `json:"_links"` + Values []ServiceDeskComment `json:"values"` +} diff --git a/cloud/servicedesk_test.go b/cloud/servicedesk_test.go index dc4c3f5d..9a9d26dc 100644 --- a/cloud/servicedesk_test.go +++ b/cloud/servicedesk_test.go @@ -429,3 +429,105 @@ func TestServiceDeskService_ListCustomers(t *testing.T) { }) } } + +func TestServiceDeskService_ListComments(t *testing.T) { + issueID := "2000" + + var gotParams struct { + Public bool + Internal bool + Start int + Limit int + } + + setup() + defer teardown() + + testMux.HandleFunc(fmt.Sprintf("/rest/servicedeskapi/request/%s/comment", issueID), func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, http.MethodGet) + testRequestURL(t, r, fmt.Sprintf("/rest/servicedeskapi/request/%s/comment", issueID)) + + qs := r.URL.Query() + gotParams.Start, _ = strconv.Atoi(qs.Get("start")) + gotParams.Limit, _ = strconv.Atoi(qs.Get("limit")) + gotParams.Public, _ = strconv.ParseBool(qs.Get("public")) + gotParams.Internal, _ = strconv.ParseBool(qs.Get("internal")) + + w.Write([]byte(`{ + "_expands": [], + "size": 1, + "start": 1, + "limit": 1, + "isLastPage": false, + "_links": { + "base": "http://host:port/context/rest/servicedeskapi", + "context": "context", + "next": "http://host:port/context/rest/servicedeskapi/request/2000/comment?start=2&limit=1", + "prev": "http://host:port/context/rest/servicedeskapi/request/2000/comment?start=0&limit=1" + }, + "values": [ + { + "id": "1000", + "body": "Hello there", + "public": true, + "author": { + "name": "fred", + "key": "fred", + "emailAddress": "fred@example.com", + "displayName": "Fred F. User", + "active": true, + "timeZone": "Australia/Sydney", + "_links": { + "jiraRest": "http://www.example.com/jira/rest/api/2/user?username=fred", + "avatarUrls": { + "48x48": "http://www.example.com/jira/secure/useravatar?size=large&ownerId=fred", + "24x24": "http://www.example.com/jira/secure/useravatar?size=small&ownerId=fred", + "16x16": "http://www.example.com/jira/secure/useravatar?size=xsmall&ownerId=fred", + "32x32": "http://www.example.com/jira/secure/useravatar?size=medium&ownerId=fred" + }, + "self": "http://www.example.com/jira/rest/api/2/user?username=fred" + } + }, + "created": { + "iso8601": "2015-10-09T10:22:00+0700", + "jira": "2015-10-09T10:22:00.000+0700", + "friendly": "Today 10:22 AM", + "epochMillis": 1444360920000 + }, + "_links": { + "self": "http://host:port/context/rest/servicedeskapi/request/2000/comment/1000" + } + } + ] + }`)) + }) + + commentList, _, err := testClient.ServiceDesk.ListComments(context.Background(), issueID, ServiceDeskCommentsListParams{ + HideInternal: true, + Start: 0, + Limit: 100, + }) + if err != nil { + t.Fatal(err) + } + + if want, got := 0, gotParams.Start; want != got { + t.Fatalf("want start: %d, got %d", want, got) + } + + if want, got := 100, gotParams.Limit; want != got { + t.Fatalf("want limit: %d, got %d", want, got) + } + + if want, got := true, gotParams.Public; want != got { + t.Fatalf("want public: %t, got %t", want, got) + } + + if want, got := false, gotParams.Internal; want != got { + t.Fatalf("want internal: %t, got %t", want, got) + } + + if want, got := 1, len(commentList.Values); want != got { + t.Fatalf("want comment length: %d, got %d", want, got) + } +}