From 1d76fca9ba3d23d82356830d4370cd7048367c97 Mon Sep 17 00:00:00 2001 From: Sol Cates Date: Mon, 8 Oct 2018 15:18:43 -0700 Subject: [PATCH 1/2] added filter support for Jira issues --- filter.go | 89 ++++++++++++++++++++++++++++++++++++++++++ filter_test.go | 56 ++++++++++++++++++++++++++ jira.go | 2 + mocks/all_filters.json | 35 +++++++++++++++++ mocks/filter.json | 33 ++++++++++++++++ 5 files changed, 215 insertions(+) create mode 100644 filter.go create mode 100644 filter_test.go create mode 100644 mocks/all_filters.json create mode 100644 mocks/filter.json diff --git a/filter.go b/filter.go new file mode 100644 index 00000000..efa00271 --- /dev/null +++ b/filter.go @@ -0,0 +1,89 @@ +package jira + +import "github.com/google/go-querystring/query" +import "fmt" + +// FilterService handles fields for the JIRA instance / API. +// +// JIRA API docs: https://developer.atlassian.com/cloud/jira/platform/rest/v3/#api-group-Filter +type FilterService struct { + client *Client +} + +// Filter represents a Filter in Jira +type Filter struct { + Self string `json:"self"` + ID string `json:"id"` + Name string `json:"name"` + Description string `json:"description"` + Owner struct { + Self string `json:"self"` + Key string `json:"key"` + AccountID string `json:"accountId"` + Name string `json:"name"` + AvatarUrls struct { + Four8X48 string `json:"48x48"` + Two4X24 string `json:"24x24"` + One6X16 string `json:"16x16"` + Three2X32 string `json:"32x32"` + } `json:"avatarUrls"` + DisplayName string `json:"displayName"` + Active bool `json:"active"` + } `json:"owner"` + Jql string `json:"jql"` + ViewURL string `json:"viewUrl"` + SearchURL string `json:"searchUrl"` + Favourite bool `json:"favourite"` + FavouritedCount int `json:"favouritedCount"` + SharePermissions []interface{} `json:"sharePermissions"` + Subscriptions struct { + Size int `json:"size"` + Items []interface{} `json:"items"` + MaxResults int `json:"max-results"` + StartIndex int `json:"start-index"` + EndIndex int `json:"end-index"` + } `json:"subscriptions"` +} + +// GetList retrieves all filters from Jira +func (fs *FilterService) GetList() ([]*Filter, *Response, error) { + + options := &GetQueryOptions{} + apiEndpoint := "rest/api/2/filter" + req, err := fs.client.NewRequest("GET", apiEndpoint, nil) + if err != nil { + return nil, nil, err + } + + if options != nil { + q, err := query.Values(options) + if err != nil { + return nil, nil, err + } + req.URL.RawQuery = q.Encode() + } + + filters := []*Filter{} + resp, err := fs.client.Do(req, &filters) + if err != nil { + jerr := NewJiraError(resp, err) + return nil, resp, jerr + } + return filters, resp, err +} + +func (fs *FilterService) Get(filterID int) (*Filter, *Response, error) { + apiEndpoint := fmt.Sprintf("rest/api/2/filter/%d", filterID) + req, err := fs.client.NewRequest("GET", apiEndpoint, nil) + if err != nil { + return nil, nil, err + } + filter := new(Filter) + resp, err := fs.client.Do(req, filter) + if err != nil { + jerr := NewJiraError(resp, err) + return nil, resp, jerr + } + + return filter, resp, err +} diff --git a/filter_test.go b/filter_test.go new file mode 100644 index 00000000..6ead48f8 --- /dev/null +++ b/filter_test.go @@ -0,0 +1,56 @@ +package jira + +import ( + "fmt" + "io/ioutil" + "net/http" + "testing" +) + +func TestFilterService_GetList(t *testing.T) { + setup() + defer teardown() + testAPIEdpoint := "/rest/api/2/filter" + raw, err := ioutil.ReadFile("./mocks/all_filters.json") + if err != nil { + t.Error(err.Error()) + } + testMux.HandleFunc(testAPIEdpoint, func(writer http.ResponseWriter, request *http.Request) { + testMethod(t, request, "GET") + testRequestURL(t, request, testAPIEdpoint) + fmt.Fprint(writer, string(raw)) + }) + + filters, _, err := testClient.Filter.GetList() + if filters == nil { + t.Error("Expected Filters list. Filters list is nil") + } + if err != nil { + t.Errorf("Error given: %s", err) + } +} + +func TestFilterService_Get(t *testing.T) { + setup() + defer teardown() + testAPIEdpoint := "/rest/api/2/filter/10000" + raw, err := ioutil.ReadFile("./mocks/filter.json") + if err != nil { + t.Error(err.Error()) + } + testMux.HandleFunc(testAPIEdpoint, func(writer http.ResponseWriter, request *http.Request) { + testMethod(t, request, "GET") + testRequestURL(t, request, testAPIEdpoint) + fmt.Fprintf(writer, string(raw)) + }) + + filter, _, err := testClient.Filter.Get(10000) + if filter == nil { + t.Errorf("Expected Filter, got nil") + } + if err != nil { + t.Errorf("Error given: %s", err) + } + + +} diff --git a/jira.go b/jira.go index d888fe7e..d8d247db 100644 --- a/jira.go +++ b/jira.go @@ -40,6 +40,7 @@ type Client struct { Component *ComponentService Resolution *ResolutionService StatusCategory *StatusCategoryService + Filter *FilterService } // NewClient returns a new JIRA API client. @@ -81,6 +82,7 @@ func NewClient(httpClient *http.Client, baseURL string) (*Client, error) { c.Component = &ComponentService{client: c} c.Resolution = &ResolutionService{client: c} c.StatusCategory = &StatusCategoryService{client: c} + c.Filter = &FilterService{client: c} return c, nil } diff --git a/mocks/all_filters.json b/mocks/all_filters.json new file mode 100644 index 00000000..50cea910 --- /dev/null +++ b/mocks/all_filters.json @@ -0,0 +1,35 @@ +[ + { + "self": "http://your-domain.atlassian.net/rest/api/2/filter/10000", + "id": "10000", + "name": "All Open Bugs", + "description": "Lists all open bugs", + "owner": { + "self": "http://your-domain.atlassian.net/rest/api/2/user?username=mia", + "key": "mia", + "accountId": "99:27935d01-92a7-4687-8272-a9b8d3b2ae2e", + "name": "mia", + "avatarUrls": { + "48x48": "http://your-domain.atlassian.net/secure/useravatar?size=large&ownerId=mia", + "24x24": "http://your-domain.atlassian.net/secure/useravatar?size=small&ownerId=mia", + "16x16": "http://your-domain.atlassian.net/secure/useravatar?size=xsmall&ownerId=mia", + "32x32": "http://your-domain.atlassian.net/secure/useravatar?size=medium&ownerId=mia" + }, + "displayName": "Mia Krystof", + "active": false + }, + "jql": "type = Bug and resolution is empty", + "viewUrl": "http://your-domain.atlassian.net/issues/?filter=10000", + "searchUrl": "http://your-domain.atlassian.net/rest/api/2/search?jql=type%20%3D%20Bug%20and%20resolutino%20is%20empty", + "favourite": true, + "favouritedCount": 0, + "sharePermissions": [], + "subscriptions": { + "size": 0, + "items": [], + "max-results": 0, + "start-index": 0, + "end-index": 0 + } + } +] diff --git a/mocks/filter.json b/mocks/filter.json new file mode 100644 index 00000000..a47141a7 --- /dev/null +++ b/mocks/filter.json @@ -0,0 +1,33 @@ +{ + "self": "http://your-domain.atlassian.net/rest/api/2/filter/10000", + "id": "10000", + "name": "All Open Bugs", + "description": "Lists all open bugs", + "owner": { + "self": "http://your-domain.atlassian.net/rest/api/2/user?username=mia", + "key": "mia", + "accountId": "99:27935d01-92a7-4687-8272-a9b8d3b2ae2e", + "name": "mia", + "avatarUrls": { + "48x48": "http://your-domain.atlassian.net/secure/useravatar?size=large&ownerId=mia", + "24x24": "http://your-domain.atlassian.net/secure/useravatar?size=small&ownerId=mia", + "16x16": "http://your-domain.atlassian.net/secure/useravatar?size=xsmall&ownerId=mia", + "32x32": "http://your-domain.atlassian.net/secure/useravatar?size=medium&ownerId=mia" + }, + "displayName": "Mia Krystof", + "active": false + }, + "jql": "type = Bug and resolution is empty", + "viewUrl": "http://your-domain.atlassian.net/issues/?filter=10000", + "searchUrl": "http://your-domain.atlassian.net/rest/api/2/search?jql=type%20%3D%20Bug%20and%20resolutino%20is%20empty", + "favourite": true, + "favouritedCount": 0, + "sharePermissions": [], + "subscriptions": { + "size": 0, + "items": [], + "max-results": 0, + "start-index": 0, + "end-index": 0 + } +} \ No newline at end of file From d53ea6050b956db1769112a8c2976a6021143d2d Mon Sep 17 00:00:00 2001 From: Sol Cates Date: Mon, 8 Oct 2018 15:55:15 -0700 Subject: [PATCH 2/2] added missing Comment for filter.Get() --- filter.go | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/filter.go b/filter.go index efa00271..1debab34 100644 --- a/filter.go +++ b/filter.go @@ -12,24 +12,11 @@ type FilterService struct { // Filter represents a Filter in Jira type Filter struct { - Self string `json:"self"` - ID string `json:"id"` - Name string `json:"name"` - Description string `json:"description"` - Owner struct { - Self string `json:"self"` - Key string `json:"key"` - AccountID string `json:"accountId"` - Name string `json:"name"` - AvatarUrls struct { - Four8X48 string `json:"48x48"` - Two4X24 string `json:"24x24"` - One6X16 string `json:"16x16"` - Three2X32 string `json:"32x32"` - } `json:"avatarUrls"` - DisplayName string `json:"displayName"` - Active bool `json:"active"` - } `json:"owner"` + Self string `json:"self"` + ID string `json:"id"` + Name string `json:"name"` + Description string `json:"description"` + Owner User `json:"owner"` Jql string `json:"jql"` ViewURL string `json:"viewUrl"` SearchURL string `json:"searchUrl"` @@ -72,6 +59,7 @@ func (fs *FilterService) GetList() ([]*Filter, *Response, error) { return filters, resp, err } +// Get retrieves a single Filter from Jira func (fs *FilterService) Get(filterID int) (*Filter, *Response, error) { apiEndpoint := fmt.Sprintf("rest/api/2/filter/%d", filterID) req, err := fs.client.NewRequest("GET", apiEndpoint, nil)